Snap for 4949134 from 237f80b0aa to qt-release
Change-Id: I4df85087586fb4187624c2c73052a2199aa4e538
This commit is contained in:
@@ -94,6 +94,7 @@
|
||||
<uses-permission android:name="android.permission.TEST_BLACKLISTED_PASSWORD" />
|
||||
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
|
||||
<uses-permission android:name="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<application android:label="@string/settings_label"
|
||||
android:icon="@drawable/ic_launcher_settings"
|
||||
@@ -201,10 +202,6 @@
|
||||
android:icon="@drawable/ic_homepage_connected_device"
|
||||
android:taskAffinity="com.android.settings"
|
||||
android:parentActivityName="Settings">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.NFC_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.BLUETOOTH_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -1486,7 +1483,6 @@
|
||||
<activity
|
||||
android:name="Settings$TextToSpeechSettingsActivity"
|
||||
android:label="@string/tts_settings"
|
||||
android:taskAffinity="com.android.settings"
|
||||
android:parentActivityName="Settings">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="com.android.settings.TTS_SETTINGS" />
|
||||
@@ -1576,9 +1572,17 @@
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
android:theme="@style/GlifTheme.Light"/>
|
||||
|
||||
<activity android:name=".biometrics.face.FaceEnrollIntroduction" android:exported="false" />
|
||||
<activity android:name=".biometrics.face.FaceEnrollEnrolling" android:exported="false" />
|
||||
<activity android:name=".biometrics.face.FaceEnrollFinish" android:exported="false" />
|
||||
<activity android:name=".biometrics.face.FaceEnrollIntroduction"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity android:name=".biometrics.face.FaceEnrollEnrolling"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity android:name=".biometrics.face.FaceEnrollFinish"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity android:name=".biometrics.fingerprint.FingerprintSettings" android:exported="false"/>
|
||||
<activity android:name=".biometrics.fingerprint.FingerprintEnrollFindSensor" android:exported="false"/>
|
||||
@@ -3110,6 +3114,10 @@
|
||||
android:label="@string/connected_device_connections_title"
|
||||
android:taskAffinity="com.android.settings"
|
||||
android:parentActivityName="Settings$ConnectedDeviceDashboardActivity">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.NFC_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="com.android.settings.ADVANCED_CONNECTED_DEVICE_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -3173,6 +3181,12 @@
|
||||
<service android:name=".fuelgauge.batterytip.AnomalyDetectionJobService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<provider
|
||||
android:name=".homepage.CardContentProvider"
|
||||
android:authorities="com.android.settings.homepage.CardContentProvider"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA" />
|
||||
|
||||
<!-- This is the longest AndroidManifest.xml ever. -->
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
<com.android.settings.fuelgauge.BatteryHistoryChart
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.android.settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:id="@+id/battery_history_chart"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
app:headerAppearance="?android:attr/textAppearanceMedium"
|
||||
android:shadowRadius="4"
|
||||
android:shadowColor="?android:attr/colorBackground"
|
||||
android:shadowDx="2"
|
||||
android:shadowDy="2"
|
||||
app:barPrimaryColor="?android:attr/colorControlActivated"
|
||||
app:barPredictionColor="@color/material_empty_color_light"
|
||||
app:chartMinHeight="@dimen/battery_history_chart_height">
|
||||
</com.android.settings.fuelgauge.BatteryHistoryChart>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.settings.dashboard.conditional.FocusRecyclerView
|
||||
<com.android.settings.homepage.conditional.FocusRecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dashboard_container"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -39,20 +39,23 @@
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
<com.android.settings.biometrics.face.FaceSquareFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- TODO: replace this with actual content-->
|
||||
<ImageView
|
||||
style="@style/SuwContentIllustration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/face_enroll_introduction" />
|
||||
<com.android.settings.biometrics.face.FaceSquareTextureView
|
||||
android:id="@+id/texture_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
<ImageView
|
||||
android:id="@+id/circle_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</com.android.settings.biometrics.face.FaceSquareFrameLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.FaceErrorText"
|
||||
|
||||
@@ -15,35 +15,6 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<declare-styleable name="BatteryHistoryChart">
|
||||
<!-- Base text color, typeface, size, and style. -->
|
||||
<attr name="android:textAppearance" />
|
||||
<!-- Text color. -->
|
||||
<attr name="android:textColor" />
|
||||
<!-- Size of the text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp). -->
|
||||
<attr name="android:textSize" />
|
||||
<!-- Typeface (normal, sans, serif, monospace) for the text. -->
|
||||
<attr name="android:typeface" />
|
||||
<!-- Style (bold, italic, bolditalic) for the text. -->
|
||||
<attr name="android:textStyle" />
|
||||
<!-- Place a shadow of the specified color behind the text. -->
|
||||
<attr name="android:shadowColor" />
|
||||
<!-- Horizontal offset of the shadow. -->
|
||||
<attr name="android:shadowDx" />
|
||||
<!-- Vertical offset of the shadow. -->
|
||||
<attr name="android:shadowDy" />
|
||||
<!-- Radius of the shadow. -->
|
||||
<attr name="android:shadowRadius" />
|
||||
<!-- Text color, typeface, size, and style of header. -->
|
||||
<attr name="headerAppearance" format="reference" />
|
||||
<!-- Primary color of chart. -->
|
||||
<attr name="barPrimaryColor" format="color|reference" />
|
||||
<!-- Color of predicted future use part of chart. -->
|
||||
<attr name="barPredictionColor" format="color|reference" />
|
||||
<!-- Minimum height of the chart itself. -->
|
||||
<attr name="chartMinHeight" format="dimension|reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="PercentageBarChart">
|
||||
<!-- Background color -->
|
||||
<attr name="emptyColor" format="color" />
|
||||
|
||||
@@ -106,9 +106,6 @@
|
||||
-->
|
||||
</string-array>
|
||||
|
||||
<!-- Whether or not we should tint the icon color on setting pages. -->
|
||||
<bool name="config_tintSettingIcon">true</bool>
|
||||
|
||||
<!-- Whether or not App & Notification screen should display recently used apps -->
|
||||
<bool name="config_display_recent_apps">true</bool>
|
||||
|
||||
@@ -133,4 +130,7 @@
|
||||
devices will be able to vary their amplitude but do not possess enough dynamic range to
|
||||
have distinct intensity levels -->
|
||||
<bool name="config_vibration_supports_multiple_intensities">false</bool>
|
||||
|
||||
<!-- Whether or not TopLevelSettings should force rounded icon for injected tiles -->
|
||||
<bool name="config_force_rounded_icon_TopLevelSettings">true</bool>
|
||||
</resources>
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
<dimen name="bind_app_widget_dialog_checkbox_bottom_padding">16dip</dimen>
|
||||
<dimen name="installed_app_details_bullet_offset">8dip</dimen>
|
||||
|
||||
<dimen name="battery_history_chart_height">120dp</dimen>
|
||||
|
||||
<dimen name="data_usage_chart_height">228dip</dimen>
|
||||
<dimen name="data_usage_chart_optimalWidth">440dip</dimen>
|
||||
<dimen name="usage_number_text_size">36sp</dimen>
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
<item name="android:navigationBarColor">#00000000</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.BluetoothPermission" parent="@android:style/Theme.Material.Light.Dialog.Alert">
|
||||
<style name="Theme.BluetoothPermission" parent="@style/Theme.AlertDialog">
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
<item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
|
||||
<item name="colorPrimaryDark">@*android:color/primary_dark_device_default_settings_light</item>
|
||||
<item name="colorAccent">@*android:color/accent_device_default_light</item>
|
||||
<item name="preferenceTheme">@style/PreferenceTheme</item>
|
||||
</style>
|
||||
|
||||
<!--TODO(b/111875856) This theme will be useless, when we add real activity/fragment to handle the full screen for WifiDialog -->
|
||||
|
||||
46
res/xml/default_autofill_picker_settings.xml
Normal file
46
res/xml/default_autofill_picker_settings.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="default_autofill_picker"
|
||||
android:title="@string/autofill_app"
|
||||
settings:keywords="@string/autofill_keywords">
|
||||
|
||||
<com.android.settings.widget.GearPreference
|
||||
android:key="default_autofill_main"
|
||||
android:title="@string/autofill_app"
|
||||
android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
|
||||
settings:keywords="@string/autofill_keywords">
|
||||
<extra android:name="for_work" android:value="false" />
|
||||
</com.android.settings.widget.GearPreference>
|
||||
|
||||
|
||||
<com.android.settings.widget.WorkOnlyCategory
|
||||
android:key="work_app_defaults"
|
||||
android:title="@string/default_for_work">
|
||||
|
||||
<com.android.settings.widget.GearPreference
|
||||
android:key="default_autofill_work"
|
||||
android:title="@string/autofill_app"
|
||||
android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
|
||||
settings:keywords="@string/autofill_keywords">
|
||||
<extra android:name="for_work" android:value="true" />
|
||||
</com.android.settings.widget.GearPreference>
|
||||
</com.android.settings.widget.WorkOnlyCategory>
|
||||
</PreferenceScreen>
|
||||
@@ -54,10 +54,10 @@
|
||||
android:persistent="false"
|
||||
android:fragment="com.android.settings.inputmethod.SpellCheckersSettings" />
|
||||
|
||||
<com.android.settings.widget.GearPreference
|
||||
<Preference
|
||||
android:key="default_autofill"
|
||||
android:title="@string/autofill_app"
|
||||
android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
|
||||
android:fragment="com.android.settings.applications.defaultapps.AutofillPicker"
|
||||
settings:keywords="@string/autofill_keywords" />
|
||||
|
||||
<!-- User dictionary preference title and fragment will be set programmatically. -->
|
||||
|
||||
125
res/xml/top_level_settings.xml
Normal file
125
res/xml/top_level_settings.xml
Normal file
@@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="top_level_settings"
|
||||
android:title="@string/settings_label_launcher">
|
||||
|
||||
<Preference
|
||||
android:key="top_level_network"
|
||||
android:title="@string/network_dashboard_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_network"
|
||||
android:order="-110"
|
||||
android:fragment="com.android.settings.network.NetworkDashboardFragment"
|
||||
settings:controller="com.android.settings.network.TopLevelNetworkEntryPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_connected_devices"
|
||||
android:title="@string/connected_devices_dashboard_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_connected_device"
|
||||
android:order="-100"
|
||||
android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
|
||||
settings:controller="com.android.settings.connecteddevice.TopLevelConnectedDevicesPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_apps_and_notifs"
|
||||
android:title="@string/app_and_notification_dashboard_title"
|
||||
android:summary="@string/app_and_notification_dashboard_summary"
|
||||
android:icon="@drawable/ic_homepage_apps"
|
||||
android:order="-90"
|
||||
android:fragment="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_battery"
|
||||
android:title="@string/power_usage_summary_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_battery"
|
||||
android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
|
||||
android:order="-80"
|
||||
settings:controller="com.android.settings.fuelgauge.TopLevelBatteryPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_display"
|
||||
android:title="@string/display_settings"
|
||||
android:summary="@string/display_dashboard_summary"
|
||||
android:icon="@drawable/ic_homepage_display"
|
||||
android:order="-70"
|
||||
android:fragment="com.android.settings.DisplaySettings"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_sound"
|
||||
android:title="@string/sound_settings"
|
||||
android:summary="@string/sound_dashboard_summary"
|
||||
android:icon="@drawable/ic_homepage_sound"
|
||||
android:order="-60"
|
||||
android:fragment="com.android.settings.notification.SoundSettings"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_storage"
|
||||
android:title="@string/storage_settings"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_storage"
|
||||
android:order="-50"
|
||||
android:fragment="com.android.settings.deviceinfo.StorageSettings"
|
||||
settings:controller="com.android.settings.deviceinfo.TopLevelStoragePreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_security"
|
||||
android:title="@string/security_settings_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_security"
|
||||
android:order="-40"
|
||||
android:fragment="com.android.settings.security.SecuritySettings"
|
||||
settings:controller="com.android.settings.security.TopLevelSecurityEntryPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_accounts"
|
||||
android:title="@string/account_dashboard_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:icon="@drawable/ic_homepage_accounts"
|
||||
android:order="-30"
|
||||
android:fragment="com.android.settings.accounts.AccountDashboardFragment"
|
||||
settings:controller="com.android.settings.accounts.TopLevelAccountEntryPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_accessibility"
|
||||
android:title="@string/accessibility_settings"
|
||||
android:summary="@string/accessibility_settings_summary"
|
||||
android:icon="@drawable/ic_homepage_accessibility"
|
||||
android:order="-20"
|
||||
android:fragment="com.android.settings.accessibility.AccessibilitySettings"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_system"
|
||||
android:title="@string/header_category_system"
|
||||
android:summary="@string/system_dashboard_summary"
|
||||
android:icon="@drawable/ic_homepage_system_dashboard"
|
||||
android:order="-10"
|
||||
android:fragment="com.android.settings.system.SystemDashboardFragment"/>
|
||||
|
||||
<Preference
|
||||
android:key="top_level_support"
|
||||
android:summary="@string/support_summary"
|
||||
android:title="@string/page_tab_title_support"
|
||||
android:icon="@drawable/ic_homepage_support"
|
||||
android:order="100"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -121,7 +121,6 @@ public class Settings extends SettingsActivity {
|
||||
}
|
||||
public static class DirectoryAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
|
||||
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class MemorySettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
@@ -39,7 +39,6 @@ import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -82,6 +81,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
||||
};
|
||||
|
||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
||||
private final BluetoothAdapter mBluetoothAdapter;
|
||||
//cache value of supporting hearing aid or not
|
||||
private boolean mHearingAidProfileSupported;
|
||||
private FragmentManager mFragmentManager;
|
||||
@@ -89,6 +89,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
||||
public AccessibilityHearingAidPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mLocalBluetoothManager = getLocalBluetoothManager();
|
||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
mHearingAidProfileSupported = isHearingAidProfileSupported();
|
||||
}
|
||||
|
||||
@@ -151,8 +152,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
||||
if (!mHearingAidProfileSupported) {
|
||||
return null;
|
||||
}
|
||||
final LocalBluetoothAdapter localAdapter = mLocalBluetoothManager.getBluetoothAdapter();
|
||||
if (!localAdapter.isEnabled()) {
|
||||
if (!mBluetoothAdapter.isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
final List<BluetoothDevice> deviceList = mLocalBluetoothManager.getProfileManager()
|
||||
@@ -166,8 +166,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
||||
}
|
||||
|
||||
private boolean isHearingAidProfileSupported() {
|
||||
final LocalBluetoothAdapter localAdapter = mLocalBluetoothManager.getBluetoothAdapter();
|
||||
final List<Integer> supportedList = localAdapter.getSupportedProfiles();
|
||||
final List<Integer> supportedList = mBluetoothAdapter.getSupportedProfiles();
|
||||
if (supportedList.contains(BluetoothProfile.HEARING_AID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.ListFormatter;
|
||||
import android.os.UserHandle;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TopLevelAccountEntryPreferenceController extends BasePreferenceController {
|
||||
public TopLevelAccountEntryPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
final AuthenticatorHelper authHelper = new AuthenticatorHelper(mContext,
|
||||
UserHandle.of(UserHandle.myUserId()), null /* OnAccountsUpdateListener */);
|
||||
final String[] types = authHelper.getEnabledAccountTypes();
|
||||
final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
|
||||
final List<CharSequence> summaries = new ArrayList<>();
|
||||
|
||||
if (types == null || types.length == 0) {
|
||||
summaries.add(mContext.getString(R.string.account_dashboard_default_summary));
|
||||
} else {
|
||||
// Show up to 3 account types, ignore any null value
|
||||
int accountToAdd = Math.min(3, types.length);
|
||||
|
||||
for (int i = 0; i < types.length && accountToAdd > 0; i++) {
|
||||
final CharSequence label = authHelper.getLabelForType(mContext, types[i]);
|
||||
if (TextUtils.isEmpty(label)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
summaries.add(bidiFormatter.unicodeWrap(label));
|
||||
accountToAdd--;
|
||||
}
|
||||
}
|
||||
return ListFormatter.getInstance().format(summaries);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package com.android.settings.applications.autofill;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.autofill.AutofillManager;
|
||||
|
||||
import com.android.settings.applications.defaultapps.DefaultAutofillPicker;
|
||||
@@ -36,7 +37,8 @@ public class AutofillPickerTrampolineActivity extends Activity {
|
||||
// First check if the current user's service already belongs to the app...
|
||||
final Intent intent = getIntent();
|
||||
final String packageName = intent.getData().getSchemeSpecificPart();
|
||||
final String currentService = DefaultAutofillPicker.getDefaultKey(this);
|
||||
final String currentService = DefaultAutofillPicker.getDefaultKey(
|
||||
this, UserHandle.myUserId());
|
||||
if (currentService != null && currentService.startsWith(packageName)) {
|
||||
// ...and succeed right away if it does.
|
||||
setResult(RESULT_OK);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.applications.defaultapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
public class AutofillPicker extends DashboardFragment {
|
||||
private static final String TAG = "AutofillPicker";
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DEFAULT_AUTOFILL_PICKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.default_autofill_picker_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
SearchIndexableResource searchIndexableResource =
|
||||
new SearchIndexableResource(context);
|
||||
searchIndexableResource.xmlResId = R.xml.default_autofill_picker_settings;
|
||||
return Arrays.asList(searchIndexableResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context
|
||||
context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
};
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
|
||||
return Arrays.asList(
|
||||
new DefaultAutofillPreferenceController(context),
|
||||
new DefaultWorkAutofillPreferenceController(context));
|
||||
}
|
||||
}
|
||||
@@ -82,12 +82,16 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC
|
||||
final Intent settingIntent = getSettingIntent(app);
|
||||
if (settingIntent != null) {
|
||||
((GearPreference) preference).setOnGearClickListener(
|
||||
p -> mContext.startActivity(settingIntent));
|
||||
p -> startActivity(settingIntent));
|
||||
} else {
|
||||
((GearPreference) preference).setOnGearClickListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void startActivity(Intent intent) {
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
protected abstract DefaultAppInfo getDefaultAppInfo();
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,25 +27,23 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.autofill.AutofillService;
|
||||
import android.service.autofill.AutofillServiceInfo;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.applications.DefaultAppInfo;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.CandidateInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
|
||||
private static final String TAG = "DefaultAutofillPicker";
|
||||
@@ -73,8 +71,10 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
activity.setResult(Activity.RESULT_CANCELED);
|
||||
activity.finish();
|
||||
};
|
||||
// If mCancelListener is not null, fragment is started from
|
||||
// ACTION_REQUEST_SET_AUTOFILL_SERVICE and we should always use the calling uid.
|
||||
mUserId = UserHandle.myUserId();
|
||||
}
|
||||
|
||||
mSettingsPackageMonitor.register(activity, activity.getMainLooper(), false);
|
||||
update();
|
||||
}
|
||||
@@ -159,8 +159,10 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
* @return The preference or {@code null} if no service can be added
|
||||
*/
|
||||
private Preference newAddServicePreferenceOrNull() {
|
||||
final String searchUri = Settings.Secure.getString(getActivity().getContentResolver(),
|
||||
Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI);
|
||||
final String searchUri = Settings.Secure.getStringForUser(
|
||||
getActivity().getContentResolver(),
|
||||
Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
|
||||
mUserId);
|
||||
if (TextUtils.isEmpty(searchUri)) {
|
||||
return null;
|
||||
}
|
||||
@@ -189,8 +191,8 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
@Override
|
||||
protected List<DefaultAppInfo> getCandidates() {
|
||||
final List<DefaultAppInfo> candidates = new ArrayList<>();
|
||||
final List<ResolveInfo> resolveInfos = mPm.queryIntentServices(
|
||||
AUTOFILL_PROBE, PackageManager.GET_META_DATA);
|
||||
final List<ResolveInfo> resolveInfos = mPm.queryIntentServicesAsUser(
|
||||
AUTOFILL_PROBE, PackageManager.GET_META_DATA, mUserId);
|
||||
final Context context = getContext();
|
||||
for (ResolveInfo info : resolveInfos) {
|
||||
final String permission = info.serviceInfo.permission;
|
||||
@@ -210,8 +212,9 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
return candidates;
|
||||
}
|
||||
|
||||
public static String getDefaultKey(Context context) {
|
||||
String setting = Settings.Secure.getString(context.getContentResolver(), SETTING);
|
||||
public static String getDefaultKey(Context context, int userId) {
|
||||
String setting = Settings.Secure.getStringForUser(
|
||||
context.getContentResolver(), SETTING, userId);
|
||||
if (setting != null) {
|
||||
ComponentName componentName = ComponentName.unflattenFromString(setting);
|
||||
if (componentName != null) {
|
||||
@@ -223,7 +226,7 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
|
||||
@Override
|
||||
protected String getDefaultKey() {
|
||||
return getDefaultKey(getContext());
|
||||
return getDefaultKey(getContext(), mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,7 +242,7 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultKey(String key) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(), SETTING, key);
|
||||
Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING, key, mUserId);
|
||||
|
||||
// Check if activity was launched from Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE
|
||||
// intent, and set proper result if so...
|
||||
@@ -263,16 +266,19 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
|
||||
|
||||
private final String mSelectedKey;
|
||||
private final Context mContext;
|
||||
private final int mUserId;
|
||||
|
||||
public AutofillSettingIntentProvider(Context context, String key) {
|
||||
public AutofillSettingIntentProvider(Context context, int userId, String key) {
|
||||
mSelectedKey = key;
|
||||
mContext = context;
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServices(
|
||||
AUTOFILL_PROBE, PackageManager.GET_META_DATA);
|
||||
final List<ResolveInfo> resolveInfos = mContext.getPackageManager()
|
||||
.queryIntentServicesAsUser(
|
||||
AUTOFILL_PROBE, PackageManager.GET_META_DATA, mUserId);
|
||||
|
||||
for (ResolveInfo resolveInfo : resolveInfos) {
|
||||
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class DefaultAutofillPreferenceController extends DefaultAppPreferenceCon
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return "default_autofill";
|
||||
return "default_autofill_main";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,7 +54,7 @@ public class DefaultAutofillPreferenceController extends DefaultAppPreferenceCon
|
||||
}
|
||||
final DefaultAutofillPicker.AutofillSettingIntentProvider intentProvider =
|
||||
new DefaultAutofillPicker.AutofillSettingIntentProvider(
|
||||
mContext, info.getKey());
|
||||
mContext, mUserId, info.getKey());
|
||||
return intentProvider.getIntent();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.applications.defaultapps;
|
||||
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settingslib.applications.DefaultAppInfo;
|
||||
|
||||
public class DefaultWorkAutofillPreferenceController extends DefaultAutofillPreferenceController {
|
||||
private final UserHandle mUserHandle;
|
||||
|
||||
public DefaultWorkAutofillPreferenceController(Context context) {
|
||||
super(context);
|
||||
mUserHandle = Utils.getManagedProfile(mUserManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mUserHandle == null) {
|
||||
return false;
|
||||
}
|
||||
return super.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return "default_autofill_work";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultAppInfo getDefaultAppInfo() {
|
||||
final String flattenComponent = Settings.Secure.getStringForUser(
|
||||
mContext.getContentResolver(),
|
||||
DefaultAutofillPicker.SETTING,
|
||||
mUserHandle.getIdentifier());
|
||||
if (!TextUtils.isEmpty(flattenComponent)) {
|
||||
DefaultAppInfo appInfo = new DefaultAppInfo(
|
||||
mContext,
|
||||
mPackageManager,
|
||||
mUserHandle.getIdentifier(),
|
||||
ComponentName.unflattenFromString(flattenComponent));
|
||||
return appInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getSettingIntent(DefaultAppInfo info) {
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
final DefaultAutofillPicker.AutofillSettingIntentProvider intentProvider =
|
||||
new DefaultAutofillPicker.AutofillSettingIntentProvider(
|
||||
mContext, mUserHandle.getIdentifier(), info.getKey());
|
||||
return intentProvider.getIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startActivity(Intent intent) {
|
||||
mContext.startActivityAsUser(intent, mUserHandle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.biometrics.face;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
/**
|
||||
* A drawable containing the circle cutout.
|
||||
*/
|
||||
public class FaceEnrollAnimationDrawable extends Drawable {
|
||||
|
||||
private Rect mBounds;
|
||||
private final Paint mSquarePaint;
|
||||
private final Paint mCircleCutoutPaint;
|
||||
|
||||
public FaceEnrollAnimationDrawable() {
|
||||
mSquarePaint = new Paint();
|
||||
mSquarePaint.setColor(Color.WHITE);
|
||||
mSquarePaint.setAntiAlias(true);
|
||||
|
||||
mCircleCutoutPaint = new Paint();
|
||||
mCircleCutoutPaint.setColor(Color.TRANSPARENT);
|
||||
mCircleCutoutPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||
mCircleCutoutPaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
mBounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mBounds == null) {
|
||||
return;
|
||||
}
|
||||
canvas.save();
|
||||
|
||||
// Draw a rectangle covering the whole view
|
||||
canvas.drawRect(0, 0, mBounds.width(), mBounds.height(), mSquarePaint);
|
||||
|
||||
// Clear a circle in the middle for the camera preview
|
||||
canvas.drawCircle(mBounds.exactCenterX(), mBounds.exactCenterY(),
|
||||
mBounds.height() / 2, mCircleCutoutPaint);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
@@ -40,10 +40,12 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
|
||||
private static final String TAG = "FaceEnrollEnrolling";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final String TAG_FACE_PREVIEW = "tag_preview";
|
||||
|
||||
private TextView mErrorText;
|
||||
private Interpolator mLinearOutSlowInInterpolator;
|
||||
private boolean mShouldFinishOnStop = true;
|
||||
private FaceEnrollPreviewFragment mFaceCameraPreview;
|
||||
|
||||
public static class FaceErrorDialog extends BiometricErrorDialog {
|
||||
static FaceErrorDialog newInstance(CharSequence msg, int msgId) {
|
||||
@@ -92,6 +94,18 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEnrollment() {
|
||||
super.startEnrollment();
|
||||
mFaceCameraPreview = (FaceEnrollPreviewFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(TAG_FACE_PREVIEW);
|
||||
if (mFaceCameraPreview == null) {
|
||||
mFaceCameraPreview = new FaceEnrollPreviewFragment();
|
||||
getSupportFragmentManager().beginTransaction().add(mFaceCameraPreview, TAG_FACE_PREVIEW)
|
||||
.commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFinishIntent() {
|
||||
return new Intent(this, FaceEnrollFinish.class);
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* 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.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraDevice;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fragment that contains the logic for showing and controlling the camera preview, circular
|
||||
* overlay, as well as the enrollment animations.
|
||||
*/
|
||||
public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment {
|
||||
|
||||
private static final String TAG = "FaceEnrollPreviewFragment";
|
||||
|
||||
private static final int MAX_PREVIEW_WIDTH = 1920;
|
||||
private static final int MAX_PREVIEW_HEIGHT = 1080;
|
||||
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private CameraManager mCameraManager;
|
||||
private String mCameraId;
|
||||
private CameraDevice mCameraDevice;
|
||||
private CaptureRequest.Builder mPreviewRequestBuilder;
|
||||
private CameraCaptureSession mCaptureSession;
|
||||
private CaptureRequest mPreviewRequest;
|
||||
private Size mPreviewSize;
|
||||
|
||||
// View used to contain the circular cutout and enrollment animation drawable
|
||||
private ImageView mCircleView;
|
||||
|
||||
// Drawable containing the circular cutout and enrollment animations
|
||||
private FaceEnrollAnimationDrawable mAnimationDrawable;
|
||||
|
||||
// Texture used for showing the camera preview
|
||||
private FaceSquareTextureView mTextureView;
|
||||
|
||||
private final TextureView.SurfaceTextureListener mSurfaceTextureListener =
|
||||
new TextureView.SurfaceTextureListener() {
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(
|
||||
SurfaceTexture surfaceTexture, int width, int height) {
|
||||
openCamera(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(
|
||||
SurfaceTexture surfaceTexture, int width, int height) {
|
||||
// Shouldn't be called, but do this for completeness.
|
||||
configureTransform(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private final CameraDevice.StateCallback mCameraStateCallback =
|
||||
new CameraDevice.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onOpened(CameraDevice cameraDevice) {
|
||||
mCameraDevice = cameraDevice;
|
||||
|
||||
try {
|
||||
// Configure the size of default buffer
|
||||
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
||||
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
||||
|
||||
// This is the output Surface we need to start preview
|
||||
Surface surface = new Surface(texture);
|
||||
|
||||
// Set up a CaptureRequest.Builder with the output Surface
|
||||
mPreviewRequestBuilder =
|
||||
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
||||
mPreviewRequestBuilder.addTarget(surface);
|
||||
|
||||
// Create a CameraCaptureSession for camera preview
|
||||
mCameraDevice.createCaptureSession(Arrays.asList(surface),
|
||||
new CameraCaptureSession.StateCallback() {
|
||||
|
||||
@Override
|
||||
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
|
||||
// The camera is already closed
|
||||
if (null == mCameraDevice) {
|
||||
return;
|
||||
}
|
||||
// When the session is ready, we start displaying the preview.
|
||||
mCaptureSession = cameraCaptureSession;
|
||||
try {
|
||||
// Auto focus should be continuous for camera preview.
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
|
||||
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||
|
||||
// Finally, we start displaying the camera preview.
|
||||
mPreviewRequest = mPreviewRequestBuilder.build();
|
||||
mCaptureSession.setRepeatingRequest(mPreviewRequest,
|
||||
null /* listener */, mHandler);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Unable to access camera", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
|
||||
Log.e(TAG, "Unable to configure camera");
|
||||
}
|
||||
}, null /* handler */);
|
||||
} catch (CameraAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(CameraDevice cameraDevice) {
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(CameraDevice cameraDevice, int error) {
|
||||
cameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FACE_ENROLL_PREVIEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mTextureView = getActivity().findViewById(R.id.texture_view);
|
||||
mCircleView = getActivity().findViewById(R.id.circle_view);
|
||||
|
||||
// Must disable hardware acceleration for this view, otherwise transparency breaks
|
||||
mCircleView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
|
||||
mAnimationDrawable = new FaceEnrollAnimationDrawable();
|
||||
mCircleView.setImageDrawable(mAnimationDrawable);
|
||||
|
||||
mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// When the screen is turned off and turned back on, the SurfaceTexture is already
|
||||
// available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
|
||||
// a camera and start preview from here (otherwise, we wait until the surface is ready in
|
||||
// the SurfaceTextureListener).
|
||||
if (mTextureView.isAvailable()) {
|
||||
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
|
||||
} else {
|
||||
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
closeCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up member variables related to camera.
|
||||
*
|
||||
* @param width The width of available size for camera preview
|
||||
* @param height The height of available size for camera preview
|
||||
*/
|
||||
private void setUpCameraOutputs(int width, int height) {
|
||||
try {
|
||||
for (String cameraId : mCameraManager.getCameraIdList()) {
|
||||
CameraCharacteristics characteristics =
|
||||
mCameraManager.getCameraCharacteristics(cameraId);
|
||||
|
||||
// Find front facing camera
|
||||
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||
if (facing == null || facing != CameraCharacteristics.LENS_FACING_FRONT) {
|
||||
continue;
|
||||
}
|
||||
mCameraId = cameraId;
|
||||
|
||||
// Get the stream configurations
|
||||
StreamConfigurationMap map = characteristics.get(
|
||||
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
|
||||
width, height, MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT);
|
||||
}
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Unable to access camera", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the camera specified by mCameraId.
|
||||
* @param width The width of the texture view
|
||||
* @param height The height of the texture view
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
try {
|
||||
setUpCameraOutputs(width, height);
|
||||
mCameraManager.openCamera(mCameraId, mCameraStateCallback, mHandler);
|
||||
configureTransform(width, height);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Unable to open camera", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the optimal resolution for the camera to open.
|
||||
*/
|
||||
private Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight,
|
||||
int maxWidth, int maxHeight) {
|
||||
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||
List<Size> bigEnough = new ArrayList<>();
|
||||
// Collect the supported resolutions that are smaller than the preview Surface
|
||||
List<Size> notBigEnough = new ArrayList<>();
|
||||
|
||||
for (Size option : choices) {
|
||||
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
|
||||
option.getHeight() == option.getWidth()) {
|
||||
if (option.getWidth() >= textureViewWidth &&
|
||||
option.getHeight() >= textureViewHeight) {
|
||||
bigEnough.add(option);
|
||||
} else {
|
||||
notBigEnough.add(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the smallest of those big enough. If there is no one big enough, pick the
|
||||
// largest of those not big enough.
|
||||
if (bigEnough.size() > 0) {
|
||||
return Collections.min(bigEnough, new CompareSizesByArea());
|
||||
} else if (notBigEnough.size() > 0) {
|
||||
return Collections.max(notBigEnough, new CompareSizesByArea());
|
||||
} else {
|
||||
Log.e(TAG, "Couldn't find any suitable preview size");
|
||||
return choices[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
|
||||
* This method should be called after the camera preview size is determined in
|
||||
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
|
||||
*
|
||||
* @param viewWidth The width of `mTextureView`
|
||||
* @param viewHeight The height of `mTextureView`
|
||||
*/
|
||||
private void configureTransform(int viewWidth, int viewHeight) {
|
||||
if (mTextureView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix the aspect ratio
|
||||
Matrix matrix = new Matrix();
|
||||
float scaleX = (float) viewWidth / mPreviewSize.getWidth();
|
||||
float scaleY = (float) viewHeight / mPreviewSize.getHeight();
|
||||
|
||||
// Now divide by smaller one so it fills up the original space
|
||||
float smaller = Math.min(scaleX, scaleY);
|
||||
scaleX = scaleX / smaller;
|
||||
scaleY = scaleY / smaller;
|
||||
|
||||
// Apply the scale
|
||||
matrix.setScale(scaleX, scaleY);
|
||||
|
||||
mTextureView.setTransform(matrix);
|
||||
}
|
||||
|
||||
private void closeCamera() {
|
||||
if (mCaptureSession != null) {
|
||||
mCaptureSession.close();
|
||||
mCaptureSession = null;
|
||||
}
|
||||
if (mCameraDevice != null) {
|
||||
mCameraDevice.close();
|
||||
mCameraDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two {@code Size}s based on their areas.
|
||||
*/
|
||||
private static class CompareSizesByArea implements Comparator<Size> {
|
||||
@Override
|
||||
public int compare(Size lhs, Size rhs) {
|
||||
// We cast here to ensure the multiplications won't overflow
|
||||
return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
|
||||
(long) rhs.getWidth() * rhs.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* Square layout that sets the height to be the same as width.
|
||||
*/
|
||||
public class FaceSquareFrameLayout extends FrameLayout {
|
||||
|
||||
public FaceSquareFrameLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FaceSquareFrameLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FaceSquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public FaceSquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// Don't call super, manually set their size below
|
||||
int size = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
// Set this frame layout to be a square
|
||||
setMeasuredDimension(size, size);
|
||||
|
||||
// Set the children to be the same size (square) as well
|
||||
final int numChildren = getChildCount();
|
||||
for (int i = 0; i < numChildren; i++) {
|
||||
int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
|
||||
this.getChildAt(i).measure(spec, spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.TextureView;
|
||||
|
||||
/**
|
||||
* A square {@link TextureView}.
|
||||
*/
|
||||
public class FaceSquareTextureView extends TextureView {
|
||||
|
||||
public FaceSquareTextureView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FaceSquareTextureView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FaceSquareTextureView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (width < height) {
|
||||
setMeasuredDimension(width, width);
|
||||
} else {
|
||||
setMeasuredDimension(height, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
@@ -115,16 +116,30 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
|
||||
* Force to update the list of bluetooth devices
|
||||
*/
|
||||
public void forceUpdate() {
|
||||
Collection<CachedBluetoothDevice> cachedDevices =
|
||||
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices =
|
||||
mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
|
||||
for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) {
|
||||
update(cachedBluetoothDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllDevicesFromPreference() {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices =
|
||||
mLocalManager.getCachedDeviceManager().getCachedDevicesCopy();
|
||||
for (CachedBluetoothDevice cachedBluetoothDevice : cachedDevices) {
|
||||
update(cachedBluetoothDevice);
|
||||
removePreference(cachedBluetoothDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
forceUpdate();
|
||||
if (BluetoothAdapter.STATE_ON == bluetoothState) {
|
||||
forceUpdate();
|
||||
} else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
|
||||
removeAllDevicesFromPreference();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.settings.slices.SliceBuilderUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
/**
|
||||
@@ -93,7 +94,7 @@ public class BluetoothSliceBuilder {
|
||||
|
||||
return new ListBuilder(context, BLUETOOTH_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.addEndItem(toggleSliceAction)
|
||||
.setPrimaryAction(primarySliceAction))
|
||||
|
||||
@@ -32,17 +32,17 @@ import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
/**
|
||||
* RequestPermissionActivity asks the user whether to enable discovery. This is
|
||||
* usually started by an application wanted to start bluetooth and or discovery
|
||||
*/
|
||||
public class RequestPermissionActivity extends Activity implements
|
||||
DialogInterface.OnClickListener {
|
||||
DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
|
||||
// Command line to test this
|
||||
// adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
|
||||
// adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE
|
||||
@@ -188,6 +188,7 @@ public class RequestPermissionActivity extends Activity implements
|
||||
builder.setNegativeButton(getString(R.string.deny), this);
|
||||
}
|
||||
|
||||
builder.setOnDismissListener(this);
|
||||
mDialog = builder.create();
|
||||
mDialog.show();
|
||||
}
|
||||
@@ -238,12 +239,16 @@ public class RequestPermissionActivity extends Activity implements
|
||||
break;
|
||||
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
cancelAndFinish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(final DialogInterface dialog) {
|
||||
cancelAndFinish();
|
||||
}
|
||||
|
||||
private void proceedAndFinish() {
|
||||
int returnCode;
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.connecteddevice;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class TopLevelConnectedDevicesPreferenceController extends BasePreferenceController {
|
||||
|
||||
public TopLevelConnectedDevicesPreferenceController(Context context,
|
||||
String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return mContext.getText(
|
||||
AdvancedConnectedDeviceController.getConnectedDevicesSummaryResourceId(mContext));
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
@@ -40,17 +39,17 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.R.id;
|
||||
import com.android.settings.dashboard.DashboardData.ConditionHeaderData;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.dashboard.conditional.ConditionAdapter;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionAdapter;
|
||||
import com.android.settings.homepage.conditional.Condition;
|
||||
import com.android.settings.homepage.conditional.ConditionAdapter;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.RoundedHomepageIcon;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
import com.android.settingslib.suggestions.SuggestionControllerMixinCompat;
|
||||
import com.android.settingslib.utils.IconCache;
|
||||
|
||||
@@ -64,7 +63,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
|
||||
@VisibleForTesting
|
||||
static final String STATE_CONDITION_EXPANDED = "condition_expanded";
|
||||
static final String META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB = "com.android.settings.bg.argb";
|
||||
|
||||
private final IconCache mCache;
|
||||
private final Context mContext;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
@@ -247,10 +246,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
return mDashboardData.getItemEntityById(itemId);
|
||||
}
|
||||
|
||||
public Suggestion getSuggestion(int position) {
|
||||
return mSuggestionAdapter.getSuggestion(position);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void notifyDashboardDataChanged(DashboardData prevData) {
|
||||
if (mFirstFrameDrawn && prevData != null) {
|
||||
@@ -321,31 +316,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
if (!TextUtils.equals(tileIcon.getResPackage(), mContext.getPackageName())
|
||||
&& !(icon instanceof RoundedHomepageIcon)) {
|
||||
icon = new RoundedHomepageIcon(mContext, icon);
|
||||
final Bundle metaData = tile.getMetaData();
|
||||
try {
|
||||
if (metaData != null) {
|
||||
// Load from bg.argb first
|
||||
int bgColor = metaData.getInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB,
|
||||
0 /* default */);
|
||||
// Not found, load from bg.hint
|
||||
if (bgColor == 0) {
|
||||
final int colorRes = metaData.getInt(
|
||||
TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
|
||||
0 /* default */);
|
||||
if (colorRes != 0) {
|
||||
bgColor = mContext.getPackageManager()
|
||||
.getResourcesForApplication(tileIcon.getResPackage())
|
||||
.getColor(colorRes, null /* theme */);
|
||||
}
|
||||
}
|
||||
// If found anything, use it.
|
||||
if (bgColor != 0) {
|
||||
((RoundedHomepageIcon) icon).setBackgroundColor(bgColor);
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Failed to set background color for " + tile.getPackageName());
|
||||
}
|
||||
((RoundedHomepageIcon) icon).setBackgroundColor(mContext, tile);
|
||||
mCache.updateIcon(tileIcon, icon);
|
||||
}
|
||||
holder.icon.setImageDrawable(icon);
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.homepage.conditional.Condition;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -35,34 +33,11 @@ public interface DashboardFeatureProvider {
|
||||
*/
|
||||
DashboardCategory getTilesForCategory(String key);
|
||||
|
||||
/**
|
||||
* Get tiles (wrapped as a list of Preference) for key defined in CategoryKey.
|
||||
*
|
||||
* @param activity Activity hosting the preference
|
||||
* @param context UI context to inflate preference
|
||||
* @param sourceMetricsCategory The context (source) from which an action is performed
|
||||
* @param key Value from CategoryKey
|
||||
* @deprecated Pages implementing {@code DashboardFragment} should use
|
||||
* {@link #getTilesForCategory(String)} instead. Using this method will not get the benefit
|
||||
* of auto-ordering, progressive disclosure, auto-refreshing summary text etc.
|
||||
*/
|
||||
@Deprecated
|
||||
List<Preference> getPreferencesForCategory(FragmentActivity activity, Context context,
|
||||
int sourceMetricsCategory, String key);
|
||||
|
||||
/**
|
||||
* Get all tiles, grouped by category.
|
||||
*/
|
||||
List<DashboardCategory> getAllCategories();
|
||||
|
||||
/**
|
||||
* Whether or not we should tint icons in setting pages.
|
||||
*
|
||||
* @deprecated in favor of color icons in homepage
|
||||
*/
|
||||
@Deprecated
|
||||
boolean shouldTintIcon();
|
||||
|
||||
/**
|
||||
* Returns an unique string key for the tile.
|
||||
*/
|
||||
@@ -72,6 +47,7 @@ public interface DashboardFeatureProvider {
|
||||
* Binds preference to data provided by tile.
|
||||
*
|
||||
* @param activity If tile contains intent to launch, it will be launched from this activity
|
||||
* @param forceRoundedIcon Whether or not injected tiles from other packages should be forced to rounded icon.
|
||||
* @param sourceMetricsCategory The context (source) from which an action is performed
|
||||
* @param pref The preference to bind data
|
||||
* @param tile The binding data
|
||||
@@ -79,8 +55,8 @@ public interface DashboardFeatureProvider {
|
||||
* @param baseOrder The order offset value. When binding, pref's order is determined by
|
||||
* both this value and tile's own priority.
|
||||
*/
|
||||
void bindPreferenceToTile(FragmentActivity activity, int sourceMetricsCategory, Preference pref,
|
||||
Tile tile, String key, int baseOrder);
|
||||
void bindPreferenceToTile(FragmentActivity activity, boolean forceRoundedIcon,
|
||||
int sourceMetricsCategory, Preference pref, Tile tile, String key, int baseOrder);
|
||||
|
||||
/**
|
||||
* Returns additional intent filter action for dashboard tiles
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.IContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
@@ -42,6 +43,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.RoundedHomepageIcon;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
@@ -49,7 +51,6 @@ import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -80,39 +81,11 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
return mCategoryManager.getTilesByCategory(mContext, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Preference> getPreferencesForCategory(FragmentActivity activity, Context context,
|
||||
int sourceMetricsCategory, String key) {
|
||||
final DashboardCategory category = getTilesForCategory(key);
|
||||
if (category == null) {
|
||||
Log.d(TAG, "NO dashboard tiles for " + TAG);
|
||||
return null;
|
||||
}
|
||||
final List<Tile> tiles = category.getTiles();
|
||||
if (tiles == null || tiles.isEmpty()) {
|
||||
Log.d(TAG, "tile list is empty, skipping category " + category.key);
|
||||
return null;
|
||||
}
|
||||
final List<Preference> preferences = new ArrayList<>();
|
||||
for (Tile tile : tiles) {
|
||||
final Preference pref = new Preference(context);
|
||||
bindPreferenceToTile(activity, sourceMetricsCategory, pref, tile, null /* key */,
|
||||
Preference.DEFAULT_ORDER /* baseOrder */);
|
||||
preferences.add(pref);
|
||||
}
|
||||
return preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DashboardCategory> getAllCategories() {
|
||||
return mCategoryManager.getCategories(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldTintIcon() {
|
||||
return mContext.getResources().getBoolean(R.bool.config_tintSettingIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDashboardKeyForTile(Tile tile) {
|
||||
if (tile == null) {
|
||||
@@ -128,8 +101,8 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPreferenceToTile(FragmentActivity activity, int sourceMetricsCategory,
|
||||
Preference pref, Tile tile, String key, int baseOrder) {
|
||||
public void bindPreferenceToTile(FragmentActivity activity, boolean forceRoundedIcon,
|
||||
int sourceMetricsCategory, Preference pref, Tile tile, String key, int baseOrder) {
|
||||
if (pref == null) {
|
||||
return;
|
||||
}
|
||||
@@ -140,7 +113,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
pref.setKey(getDashboardKeyForTile(tile));
|
||||
}
|
||||
bindSummary(pref, tile);
|
||||
bindIcon(pref, tile);
|
||||
bindIcon(pref, tile, forceRoundedIcon);
|
||||
final Bundle metadata = tile.getMetaData();
|
||||
String clsName = null;
|
||||
String action = null;
|
||||
@@ -220,10 +193,16 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void bindIcon(Preference preference, Tile tile) {
|
||||
void bindIcon(Preference preference, Tile tile, boolean forceRoundedIcon) {
|
||||
final Icon tileIcon = tile.getIcon(mContext);
|
||||
if (tileIcon != null) {
|
||||
preference.setIcon(tileIcon.loadDrawable(preference.getContext()));
|
||||
Drawable iconDrawable = tileIcon.loadDrawable(preference.getContext());
|
||||
if (forceRoundedIcon
|
||||
&& !TextUtils.equals(mContext.getPackageName(), tile.getPackageName())) {
|
||||
iconDrawable = new RoundedHomepageIcon(mContext, iconDrawable);
|
||||
((RoundedHomepageIcon) iconDrawable).setBackgroundColor(mContext, tile);
|
||||
}
|
||||
preference.setIcon(iconDrawable);
|
||||
} else if (tile.getMetaData() != null
|
||||
&& tile.getMetaData().containsKey(META_DATA_PREFERENCE_ICON_URI)) {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
|
||||
@@ -207,6 +207,10 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
@Override
|
||||
protected abstract int getPreferenceScreenResId();
|
||||
|
||||
protected boolean shouldForceRoundedIcon() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
|
||||
List<AbstractPreferenceController> controllerList = mPreferenceControllers.get(clazz);
|
||||
if (controllerList != null) {
|
||||
@@ -343,6 +347,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
final int tintColor = a.getColor(0, context.getColor(android.R.color.white));
|
||||
a.recycle();
|
||||
// Install dashboard tiles.
|
||||
final boolean forceRoundedIcons = shouldForceRoundedIcon();
|
||||
for (Tile tile : tiles) {
|
||||
final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
@@ -361,13 +366,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
if (mDashboardTilePrefKeys.contains(key)) {
|
||||
// Have the key already, will rebind.
|
||||
final Preference preference = screen.findPreference(key);
|
||||
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), getMetricsCategory(),
|
||||
preference, tile, key, mPlaceholderPreferenceController.getOrder());
|
||||
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
|
||||
getMetricsCategory(), preference, tile, key,
|
||||
mPlaceholderPreferenceController.getOrder());
|
||||
} else {
|
||||
// Don't have this key, add it.
|
||||
final Preference pref = new Preference(getPrefContext());
|
||||
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), getMetricsCategory(),
|
||||
pref, tile, key, mPlaceholderPreferenceController.getOrder());
|
||||
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
|
||||
getMetricsCategory(), pref, tile, key,
|
||||
mPlaceholderPreferenceController.getOrder());
|
||||
screen.addPreference(pref);
|
||||
mDashboardTilePrefKeys.add(key);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.settings.deviceinfo.StorageDashboardFragment;
|
||||
import com.android.settings.display.NightDisplaySettings;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.gestures.GestureSettings;
|
||||
import com.android.settings.homepage.TopLevelSettings;
|
||||
import com.android.settings.language.LanguageAndInputSettings;
|
||||
import com.android.settings.network.NetworkDashboardFragment;
|
||||
import com.android.settings.notification.ConfigureNotificationSettings;
|
||||
@@ -61,6 +62,9 @@ public class DashboardFragmentRegistry {
|
||||
|
||||
static {
|
||||
PARENT_TO_CATEGORY_KEY_MAP = new ArrayMap<>();
|
||||
// TODO(b/110405144): Add the mapping when IA.homepage intent-filter is is removed.
|
||||
// PARENT_TO_CATEGORY_KEY_MAP.put(TopLevelSettings.class.getName(),
|
||||
// CategoryKey.CATEGORY_HOMEPAGE);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(
|
||||
NetworkDashboardFragment.class.getName(), CategoryKey.CATEGORY_NETWORK);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(ConnectedDeviceDashboardFragment.class.getName(),
|
||||
@@ -98,9 +102,9 @@ public class DashboardFragmentRegistry {
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(ZenModeSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_DO_NOT_DISTURB);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(GestureSettings.class.getName(),
|
||||
CategoryKey.CATEGORY_GESTURES);
|
||||
CategoryKey.CATEGORY_GESTURES);
|
||||
PARENT_TO_CATEGORY_KEY_MAP.put(NightDisplaySettings.class.getName(),
|
||||
CategoryKey.CATEGORY_NIGHT_DISPLAY);
|
||||
CategoryKey.CATEGORY_NIGHT_DISPLAY);
|
||||
|
||||
CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
|
||||
|
||||
|
||||
@@ -26,17 +26,22 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settings.core.SettingsBaseActivity;
|
||||
import com.android.settings.core.SettingsBaseActivity.CategoryListener;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.dashboard.conditional.ConditionManager;
|
||||
import com.android.settings.dashboard.conditional.ConditionManager.ConditionListener;
|
||||
import com.android.settings.dashboard.conditional.FocusRecyclerView;
|
||||
import com.android.settings.dashboard.conditional.FocusRecyclerView.FocusListener;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
||||
import com.android.settings.homepage.conditional.Condition;
|
||||
import com.android.settings.homepage.conditional.ConditionManager;
|
||||
import com.android.settings.homepage.conditional.ConditionManager.ConditionListener;
|
||||
import com.android.settings.homepage.conditional.FocusRecyclerView;
|
||||
import com.android.settings.homepage.conditional.FocusRecyclerView.FocusListener;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.ActionBarShadowController;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
@@ -46,11 +51,12 @@ import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
/**
|
||||
* Deprecated in favor of {@link com.android.settings.homepage.TopLevelSettings}
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public class DashboardSummary extends InstrumentedFragment
|
||||
implements CategoryListener, ConditionListener,
|
||||
FocusListener, SuggestionControllerMixinCompat.SuggestionControllerHost {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.deviceinfo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.text.format.Formatter;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
|
||||
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class TopLevelStoragePreferenceController extends BasePreferenceController {
|
||||
|
||||
private final StorageManager mStorageManager;
|
||||
private final StorageManagerVolumeProvider mStorageManagerVolumeProvider;
|
||||
|
||||
public TopLevelStoragePreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mStorageManager = mContext.getSystemService(StorageManager.class);
|
||||
mStorageManagerVolumeProvider = new StorageManagerVolumeProvider(mStorageManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
// TODO: Register listener.
|
||||
final NumberFormat percentageFormat = NumberFormat.getPercentInstance();
|
||||
final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
|
||||
mStorageManagerVolumeProvider);
|
||||
double privateUsedBytes = info.totalBytes - info.freeBytes;
|
||||
return mContext.getString(R.string.storage_summary,
|
||||
percentageFormat.format(privateUsedBytes / info.totalBytes),
|
||||
Formatter.formatFileSize(mContext, info.freeBytes));
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import com.android.settings.slices.SliceBroadcastReceiver;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
|
||||
@@ -93,7 +94,7 @@ public class FlashlightSliceBuilder {
|
||||
IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
|
||||
return new ListBuilder(context, FLASHLIGHT_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(context.getText(R.string.power_flashlight))
|
||||
.setTitleItem(icon, ICON_IMAGE)
|
||||
.setPrimaryAction(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.fuelgauge;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryStats.HistoryItem;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.fuelgauge.BatteryActiveView.BatteryActiveProvider;
|
||||
import com.android.settings.widget.UsageView;
|
||||
|
||||
public class BatteryHistoryDetail extends SettingsPreferenceFragment {
|
||||
public static final String EXTRA_STATS = "stats";
|
||||
public static final String EXTRA_BROADCAST = "broadcast";
|
||||
public static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
|
||||
|
||||
private BatteryStats mStats;
|
||||
private Intent mBatteryBroadcast;
|
||||
|
||||
private BatteryFlagParser mChargingParser;
|
||||
private BatteryFlagParser mScreenOn;
|
||||
private BatteryFlagParser mGpsParser;
|
||||
private BatteryFlagParser mFlashlightParser;
|
||||
private BatteryFlagParser mCameraParser;
|
||||
private BatteryWifiParser mWifiParser;
|
||||
private BatteryFlagParser mCpuParser;
|
||||
private BatteryCellParser mPhoneParser;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
String histFile = getArguments().getString(EXTRA_STATS);
|
||||
mStats = BatteryStatsHelper.statsFromFile(getActivity(), histFile);
|
||||
mBatteryBroadcast = getArguments().getParcelable(EXTRA_BROADCAST);
|
||||
|
||||
TypedValue value = new TypedValue();
|
||||
getContext().getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
|
||||
int accentColor = getContext().getColor(value.resourceId);
|
||||
|
||||
mChargingParser = new BatteryFlagParser(accentColor, false,
|
||||
HistoryItem.STATE_BATTERY_PLUGGED_FLAG);
|
||||
mScreenOn = new BatteryFlagParser(accentColor, false,
|
||||
HistoryItem.STATE_SCREEN_ON_FLAG);
|
||||
mGpsParser = new BatteryFlagParser(accentColor, false,
|
||||
HistoryItem.STATE_GPS_ON_FLAG);
|
||||
mFlashlightParser = new BatteryFlagParser(accentColor, true,
|
||||
HistoryItem.STATE2_FLASHLIGHT_FLAG);
|
||||
mCameraParser = new BatteryFlagParser(accentColor, true,
|
||||
HistoryItem.STATE2_CAMERA_FLAG);
|
||||
mWifiParser = new BatteryWifiParser(accentColor);
|
||||
mCpuParser = new BatteryFlagParser(accentColor, false,
|
||||
HistoryItem.STATE_CPU_RUNNING_FLAG);
|
||||
mPhoneParser = new BatteryCellParser();
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.battery_history_detail, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
updateEverything();
|
||||
}
|
||||
|
||||
private void updateEverything() {
|
||||
BatteryInfo.getBatteryInfo(getContext(), info -> {
|
||||
final View view = getView();
|
||||
info.bindHistory((UsageView) view.findViewById(R.id.battery_usage), mChargingParser,
|
||||
mScreenOn, mGpsParser, mFlashlightParser, mCameraParser, mWifiParser,
|
||||
mCpuParser, mPhoneParser);
|
||||
((TextView) view.findViewById(R.id.charge)).setText(info.batteryPercentString);
|
||||
((TextView) view.findViewById(R.id.estimation)).setText(info.remainingLabel);
|
||||
|
||||
bindData(mChargingParser, R.string.battery_stats_charging_label, R.id.charging_group);
|
||||
bindData(mScreenOn, R.string.battery_stats_screen_on_label, R.id.screen_on_group);
|
||||
bindData(mGpsParser, R.string.battery_stats_gps_on_label, R.id.gps_group);
|
||||
bindData(mFlashlightParser, R.string.battery_stats_flashlight_on_label,
|
||||
R.id.flashlight_group);
|
||||
bindData(mCameraParser, R.string.battery_stats_camera_on_label, R.id.camera_group);
|
||||
bindData(mWifiParser, R.string.battery_stats_wifi_running_label, R.id.wifi_group);
|
||||
bindData(mCpuParser, R.string.battery_stats_wake_lock_label, R.id.cpu_group);
|
||||
bindData(mPhoneParser, R.string.battery_stats_phone_signal_label,
|
||||
R.id.cell_network_group);
|
||||
}, mStats, false /* shortString */);
|
||||
}
|
||||
|
||||
private void bindData(BatteryActiveProvider provider, int label, int groupId) {
|
||||
View group = getView().findViewById(groupId);
|
||||
group.setVisibility(provider.hasData() ? View.VISIBLE : View.GONE);
|
||||
((TextView) group.findViewById(android.R.id.title)).setText(label);
|
||||
((BatteryActiveView) group.findViewById(R.id.battery_active)).setProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FUELGAUGE_BATTERY_HISTORY_DETAIL;
|
||||
}
|
||||
}
|
||||
@@ -22,19 +22,16 @@ import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.dashboard.conditional.BatterySaverCondition;
|
||||
import com.android.settings.dashboard.conditional.ConditionManager;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
public class BatterySaverController extends BasePreferenceController
|
||||
implements LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
|
||||
private static final String KEY_BATTERY_SAVER = "battery_saver_summary";
|
||||
@@ -82,11 +79,6 @@ public class BatterySaverController extends BasePreferenceController
|
||||
mBatteryStateChangeReceiver.setListening(false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshConditionManager() {
|
||||
ConditionManager.get(mContext).getCondition(BatterySaverCondition.class).refreshState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
final boolean isPowerSaveOn = mPowerManager.isPowerSaveMode();
|
||||
|
||||
@@ -72,8 +72,6 @@ public abstract class PowerUsageBase extends DashboardFragment {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryDetail.BATTERY_HISTORY_FILE);
|
||||
mBatteryBroadcastReceiver.register();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType;
|
||||
import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.format.Formatter;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -32,6 +32,11 @@ import android.view.View;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
@@ -51,11 +56,6 @@ import com.android.settingslib.utils.StringUtil;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
/**
|
||||
* Displays a list of apps and subsystems that consume power, ordered by how much power was
|
||||
* consumed since the last time it was unplugged.
|
||||
@@ -147,9 +147,9 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
|
||||
protected void updateViews(List<BatteryInfo> batteryInfos) {
|
||||
final BatteryMeterView batteryView = mBatteryLayoutPref
|
||||
.findViewById(R.id.battery_header_icon);
|
||||
.findViewById(R.id.battery_header_icon);
|
||||
final TextView percentRemaining =
|
||||
mBatteryLayoutPref.findViewById(R.id.battery_percent);
|
||||
mBatteryLayoutPref.findViewById(R.id.battery_percent);
|
||||
final TextView summary1 = mBatteryLayoutPref.findViewById(R.id.summary1);
|
||||
final TextView summary2 = mBatteryLayoutPref.findViewById(R.id.summary2);
|
||||
BatteryInfo oldInfo = batteryInfos.get(0);
|
||||
@@ -160,13 +160,13 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
// can sometimes say 0 time remaining because battery stats requires the phone
|
||||
// be unplugged for a period of time before being willing ot make an estimate.
|
||||
summary1.setText(mPowerFeatureProvider.getOldEstimateDebugString(
|
||||
Formatter.formatShortElapsedTime(getContext(),
|
||||
PowerUtil.convertUsToMs(oldInfo.remainingTimeUs))));
|
||||
Formatter.formatShortElapsedTime(getContext(),
|
||||
PowerUtil.convertUsToMs(oldInfo.remainingTimeUs))));
|
||||
|
||||
// for this one we can just set the string directly
|
||||
summary2.setText(mPowerFeatureProvider.getEnhancedEstimateDebugString(
|
||||
Formatter.formatShortElapsedTime(getContext(),
|
||||
PowerUtil.convertUsToMs(newInfo.remainingTimeUs))));
|
||||
Formatter.formatShortElapsedTime(getContext(),
|
||||
PowerUtil.convertUsToMs(newInfo.remainingTimeUs))));
|
||||
|
||||
batteryView.setBatteryLevel(oldInfo.batteryLevel);
|
||||
batteryView.setCharging(!oldInfo.discharging);
|
||||
@@ -419,19 +419,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static CharSequence getDashboardLabel(Context context, BatteryInfo info) {
|
||||
CharSequence label;
|
||||
final BidiFormatter formatter = BidiFormatter.getInstance();
|
||||
if (info.remainingLabel == null) {
|
||||
label = info.batteryPercentString;
|
||||
} else {
|
||||
label = context.getString(R.string.power_remaining_settings_home_page,
|
||||
formatter.unicodeWrap(info.batteryPercentString),
|
||||
formatter.unicodeWrap(info.remainingLabel));
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.fuelgauge;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.BidiFormatter;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
|
||||
LifecycleObserver, OnStart, OnStop {
|
||||
|
||||
private final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
|
||||
private Preference mPreference;
|
||||
private BatteryInfo mBatteryInfo;
|
||||
|
||||
public TopLevelBatteryPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
|
||||
mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
|
||||
BatteryInfo.getBatteryInfo(mContext, info -> {
|
||||
mBatteryInfo = info;
|
||||
updateState(mPreference);
|
||||
}, true /* shortString */);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mBatteryBroadcastReceiver.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mBatteryBroadcastReceiver.unRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return getDashboardLabel(mContext, mBatteryInfo);
|
||||
}
|
||||
|
||||
static CharSequence getDashboardLabel(Context context, BatteryInfo info) {
|
||||
if (info == null || context == null) {
|
||||
return null;
|
||||
}
|
||||
CharSequence label;
|
||||
final BidiFormatter formatter = BidiFormatter.getInstance();
|
||||
if (info.remainingLabel == null) {
|
||||
label = info.batteryPercentString;
|
||||
} else {
|
||||
label = context.getString(R.string.power_remaining_settings_home_page,
|
||||
formatter.unicodeWrap(info.batteryPercentString),
|
||||
formatter.unicodeWrap(info.remainingLabel));
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
166
src/com/android/settings/homepage/CardContentProvider.java
Normal file
166
src/com/android/settings/homepage/CardContentProvider.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.StrictMode;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Provider stores and manages user interaction feedback for homepage contextual cards.
|
||||
*/
|
||||
public class CardContentProvider extends ContentProvider {
|
||||
|
||||
private static final String TAG = "CardContentProvider";
|
||||
|
||||
public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider";
|
||||
|
||||
/** URI matcher for ContentProvider queries. */
|
||||
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
/** URI matcher type for cards table */
|
||||
private static final int MATCH_CARDS = 100;
|
||||
/** URI matcher type for card log table */
|
||||
private static final int MATCH_CARD_LOG = 200;
|
||||
|
||||
static {
|
||||
sUriMatcher.addURI(CARD_AUTHORITY, CardDatabaseHelper.CARD_TABLE, MATCH_CARDS);
|
||||
}
|
||||
|
||||
private CardDatabaseHelper mDBHelper;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
mDBHelper = CardDatabaseHelper.getInstance(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
if (Build.IS_DEBUGGABLE) {
|
||||
enableStrictMode(true);
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
|
||||
final String table = getTableFromMatch(uri);
|
||||
final long ret = database.insert(table, null, values);
|
||||
if (ret != -1) {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
} else {
|
||||
Log.e(TAG, "The CardContentProvider insertion failed! Plase check SQLiteDatabase's "
|
||||
+ "message.");
|
||||
}
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
if (Build.IS_DEBUGGABLE) {
|
||||
enableStrictMode(true);
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
|
||||
final String table = getTableFromMatch(uri);
|
||||
final int rowsDeleted = database.delete(table, selection, selectionArgs);
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return rowsDeleted;
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
throw new UnsupportedOperationException("getType operation not supported currently.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection,
|
||||
String[] selectionArgs, String sortOrder) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
if (Build.IS_DEBUGGABLE) {
|
||||
enableStrictMode(true);
|
||||
}
|
||||
|
||||
final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
|
||||
final String table = getTableFromMatch(uri);
|
||||
queryBuilder.setTables(table);
|
||||
final SQLiteDatabase database = mDBHelper.getReadableDatabase();
|
||||
final Cursor cursor = queryBuilder.query(database,
|
||||
projection, selection, selectionArgs, null, null, sortOrder);
|
||||
|
||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return cursor;
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
if (Build.IS_DEBUGGABLE) {
|
||||
enableStrictMode(true);
|
||||
}
|
||||
|
||||
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
|
||||
final String table = getTableFromMatch(uri);
|
||||
final int rowsUpdated = database.update(table, values, selection, selectionArgs);
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return rowsUpdated;
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableStrictMode(boolean enabled) {
|
||||
StrictMode.setThreadPolicy(enabled
|
||||
? new StrictMode.ThreadPolicy.Builder().detectAll().build()
|
||||
: StrictMode.ThreadPolicy.LAX);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String getTableFromMatch(Uri uri) {
|
||||
final int match = sUriMatcher.match(uri);
|
||||
String table;
|
||||
switch (match) {
|
||||
case MATCH_CARDS:
|
||||
table = CardDatabaseHelper.CARD_TABLE;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown Uri format: " + uri);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
}
|
||||
190
src/com/android/settings/homepage/CardDatabaseHelper.java
Normal file
190
src/com/android/settings/homepage/CardDatabaseHelper.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Defines the schema for the Homepage Cards database.
|
||||
*/
|
||||
public class CardDatabaseHelper extends SQLiteOpenHelper {
|
||||
private static final String DATABASE_NAME = "homepage_cards.db";
|
||||
private static final int DATABASE_VERSION = 1;
|
||||
|
||||
public static final String CARD_TABLE = "cards";
|
||||
|
||||
public interface CardColumns {
|
||||
/**
|
||||
* Primary key. Name of the card.
|
||||
*/
|
||||
String NAME = "name";
|
||||
|
||||
/**
|
||||
* Type of the card.
|
||||
*/
|
||||
String TYPE = "type";
|
||||
|
||||
/**
|
||||
* Score of the card. Higher numbers have higher priorities.
|
||||
*/
|
||||
String SCORE = "score";
|
||||
|
||||
/**
|
||||
* URI of the slice card.
|
||||
*/
|
||||
String SLICE_URI = "slice_uri";
|
||||
|
||||
/**
|
||||
* Category of the card. The value is between 0 to 3.
|
||||
*/
|
||||
String CATEGORY = "category";
|
||||
|
||||
/**
|
||||
* URI decides the card can be shown.
|
||||
*/
|
||||
String AVAILABILITY_URI = "availability_uri";
|
||||
|
||||
/**
|
||||
* Keep the card last display's locale.
|
||||
*/
|
||||
String LOCALIZED_TO_LOCALE = "localized_to_locale";
|
||||
|
||||
/**
|
||||
* Package name for all card candidates.
|
||||
*/
|
||||
String PACKAGE_NAME = "package_name";
|
||||
|
||||
/**
|
||||
* Application version of the package.
|
||||
*/
|
||||
String APP_VERSION = "app_version";
|
||||
|
||||
/**
|
||||
* Title resource name of the package.
|
||||
*/
|
||||
String TITLE_RES_NAME = "title_res_name";
|
||||
|
||||
/**
|
||||
* Title of the package to be shown.
|
||||
*/
|
||||
String TITLE_TEXT = "title_text";
|
||||
|
||||
/**
|
||||
* Summary resource name of the package.
|
||||
*/
|
||||
String SUMMARY_RES_NAME = "summary_res_name";
|
||||
|
||||
/**
|
||||
* Summary of the package to be shown.
|
||||
*/
|
||||
String SUMMARY_TEXT = "summary_text";
|
||||
|
||||
/**
|
||||
* Icon resource name of the package.
|
||||
*/
|
||||
String ICON_RES_NAME = "icon_res_name";
|
||||
|
||||
/**
|
||||
* Icon resource id of the package.
|
||||
*/
|
||||
String ICON_RES_ID = "icon_res_id";
|
||||
|
||||
/**
|
||||
* PendingIntent for for custom view card candidate. Do action when user press card.
|
||||
*/
|
||||
String CARD_ACTION = "card_action";
|
||||
|
||||
/**
|
||||
* Expire time of the card. The unit of the value is mini-second.
|
||||
*/
|
||||
String EXPIRE_TIME_MS = "expire_time_ms";
|
||||
}
|
||||
|
||||
private static final String CREATE_CARD_TABLE =
|
||||
"CREATE TABLE " + CARD_TABLE +
|
||||
"(" +
|
||||
CardColumns.NAME +
|
||||
" TEXT NOT NULL PRIMARY KEY, " +
|
||||
CardColumns.TYPE +
|
||||
" INTEGER NOT NULL, " +
|
||||
CardColumns.SCORE +
|
||||
" DOUBLE NOT NULL, " +
|
||||
CardColumns.SLICE_URI +
|
||||
" TEXT, " +
|
||||
CardColumns.CATEGORY +
|
||||
" INTEGER DEFAULT 0 CHECK (" +
|
||||
CardColumns.CATEGORY +
|
||||
" >= 0 AND " +
|
||||
CardColumns.CATEGORY +
|
||||
" <= 3), " +
|
||||
CardColumns.AVAILABILITY_URI +
|
||||
" TEXT, " +
|
||||
CardColumns.LOCALIZED_TO_LOCALE +
|
||||
" TEXT, " +
|
||||
CardColumns.PACKAGE_NAME +
|
||||
" TEXT NOT NULL, " +
|
||||
CardColumns.APP_VERSION +
|
||||
" TEXT NOT NULL, " +
|
||||
CardColumns.TITLE_RES_NAME +
|
||||
" TEXT, " +
|
||||
CardColumns.TITLE_TEXT +
|
||||
" TEXT, " +
|
||||
CardColumns.SUMMARY_RES_NAME +
|
||||
" TEXT, " +
|
||||
CardColumns.SUMMARY_TEXT +
|
||||
" TEXT, " +
|
||||
CardColumns.ICON_RES_NAME +
|
||||
" TEXT, " +
|
||||
CardColumns.ICON_RES_ID +
|
||||
" INTEGER DEFAULT 0, " +
|
||||
CardColumns.CARD_ACTION +
|
||||
" TEXT, " +
|
||||
CardColumns.EXPIRE_TIME_MS +
|
||||
" INTEGER " +
|
||||
");";
|
||||
|
||||
public CardDatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_CARD_TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion < newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + CARD_TABLE);
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static CardDatabaseHelper sCardDatabaseHelper;
|
||||
|
||||
public static synchronized CardDatabaseHelper getInstance(Context context) {
|
||||
if (sCardDatabaseHelper == null) {
|
||||
sCardDatabaseHelper = new CardDatabaseHelper(context.getApplicationContext());
|
||||
}
|
||||
return sCardDatabaseHelper;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsHomepageActivity;
|
||||
@@ -39,8 +41,6 @@ import com.google.android.material.bottomappbar.BottomAppBar;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class HomepageFragment extends InstrumentedFragment {
|
||||
|
||||
private static final String TAG = "HomepageFragment";
|
||||
@@ -70,7 +70,7 @@ public class HomepageFragment extends InstrumentedFragment {
|
||||
|
||||
private void setupBottomBar() {
|
||||
final Activity activity = getActivity();
|
||||
mSearchButton = (FloatingActionButton) activity.findViewById(R.id.search_fab);
|
||||
mSearchButton = activity.findViewById(R.id.search_fab);
|
||||
|
||||
mSearchButton.setOnClickListener(v -> {
|
||||
final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
|
||||
@@ -79,7 +79,7 @@ public class HomepageFragment extends InstrumentedFragment {
|
||||
startActivityForResult(intent, 0 /* requestCode */);
|
||||
});
|
||||
mBottomSheetBehavior = BottomSheetBehavior.from(activity.findViewById(R.id.bottom_sheet));
|
||||
final BottomAppBar bottomBar = (BottomAppBar) activity.findViewById(R.id.bar);
|
||||
final BottomAppBar bottomBar = activity.findViewById(R.id.bar);
|
||||
bottomBar.setOnClickListener(v -> {
|
||||
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
||||
});
|
||||
@@ -87,7 +87,7 @@ public class HomepageFragment extends InstrumentedFragment {
|
||||
final int screenWidthpx = getResources().getDisplayMetrics().widthPixels;
|
||||
final View searchbar = activity.findViewById(R.id.search_bar_container);
|
||||
final View bottombar = activity.findViewById(R.id.bar);
|
||||
final Toolbar searchActionBar = (Toolbar) activity.findViewById(R.id.search_action_bar);
|
||||
final Toolbar searchActionBar = activity.findViewById(R.id.search_action_bar);
|
||||
searchActionBar.setNavigationIcon(R.drawable.ic_search_floating_24dp);
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ public class HomepageFragment extends InstrumentedFragment {
|
||||
@Override
|
||||
public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
||||
if (!mBottomFragmentLoaded) {
|
||||
// TODO(b/110405144): Switch to {@link TopLevelSettings} when it's ready.
|
||||
SettingsHomepageActivity.switchToFragment(getActivity(),
|
||||
R.id.bottom_sheet_fragment, DashboardSummary.class.getName());
|
||||
mBottomFragmentLoaded = true;
|
||||
|
||||
116
src/com/android/settings/homepage/TopLevelSettings.java
Normal file
116
src/com/android/settings/homepage/TopLevelSettings.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import static com.android.settings.search.actionbar.SearchMenuController
|
||||
.NEED_SEARCH_ICON_IN_ACTION_BAR;
|
||||
import static com.android.settingslib.search.SearchIndexable.MOBILE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
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.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable(forTarget = MOBILE)
|
||||
public class TopLevelSettings extends DashboardFragment implements
|
||||
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
|
||||
|
||||
private static final String TAG = "TopLevelSettings";
|
||||
|
||||
public TopLevelSettings() {
|
||||
final Bundle args = new Bundle();
|
||||
// Disable the search icon because this page uses a full search view in actionbar.
|
||||
args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false);
|
||||
setArguments(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.top_level_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DASHBOARD_SUMMARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
// Disable the help icon because this page uses a full search view in actionbar.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getCallbackFragment() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
|
||||
new SubSettingLauncher(getActivity())
|
||||
.setDestination(pref.getFragment())
|
||||
.setArguments(pref.getExtras())
|
||||
.setSourceMetricsCategory(caller instanceof Instrumentable
|
||||
? ((Instrumentable) caller).getMetricsCategory()
|
||||
: Instrumentable.METRICS_CATEGORY_UNKNOWN)
|
||||
.setTitleRes(-1)
|
||||
.launch();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldForceRoundedIcon() {
|
||||
return getContext().getResources()
|
||||
.getBoolean(R.bool.config_force_rounded_icon_TopLevelSettings);
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.top_level_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
// Never searchable, all entries in this page are already indexed elsewhere.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -8,7 +8,7 @@
|
||||
* 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.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -22,12 +22,12 @@ import android.content.IntentFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
public abstract class Condition {
|
||||
|
||||
private static final String KEY_SILENCE = "silence";
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
@@ -22,6 +22,10 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
|
||||
@@ -32,10 +36,6 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class ConditionAdapter extends RecyclerView.Adapter<DashboardItemHolder> {
|
||||
public static final String TAG = "ConditionAdapter";
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
@@ -44,7 +44,7 @@ public class ConditionManager implements LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String PKG = "com.android.settings.dashboard.conditional.";
|
||||
private static final String PKG = "com.android.settings.homepage.conditional.";
|
||||
|
||||
private static final String FILE_NAME = "condition_state.xml";
|
||||
private static final String TAG_CONDITIONS = "cs";
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -26,13 +26,13 @@ import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.notification.ZenModeSettings;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
public class DndCondition extends Condition {
|
||||
|
||||
private static final String TAG = "DndCondition";
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import static android.content.Context.NOTIFICATION_SERVICE;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard.conditional;
|
||||
package com.android.settings.homepage.conditional;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -27,10 +27,10 @@ import android.speech.tts.TtsEngines;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.inputmethod.PhysicalKeyboardPreferenceController;
|
||||
@@ -41,14 +41,10 @@ import com.android.settings.widget.PreferenceCategoryController;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@SearchIndexable
|
||||
public class LanguageAndInputSettings extends DashboardFragment {
|
||||
|
||||
@@ -122,7 +118,6 @@ public class LanguageAndInputSettings extends DashboardFragment {
|
||||
|
||||
// Input Assistance
|
||||
controllers.add(new SpellCheckerPreferenceController(context));
|
||||
controllers.add(new DefaultAutofillPreferenceController(context));
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.settings.slices.SliceBuilderUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
/**
|
||||
@@ -70,7 +71,7 @@ public class LocationSliceBuilder {
|
||||
|
||||
return new ListBuilder(context, LOCATION_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.setTitleItem(icon, ICON_IMAGE)
|
||||
.setPrimaryAction(primarySliceAction))
|
||||
|
||||
@@ -49,6 +49,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
/**
|
||||
@@ -183,7 +184,7 @@ public class Enhanced4gLteSliceHelper {
|
||||
|
||||
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
|
||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(getEnhanced4glteModeTitle(subId))
|
||||
.addEndItem(
|
||||
new SliceAction(
|
||||
|
||||
@@ -149,6 +149,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(b/110405144): Remove SummaryProvider
|
||||
@VisibleForTesting
|
||||
static class SummaryProvider implements SummaryLoader.SummaryProvider {
|
||||
|
||||
|
||||
@@ -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.network;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.ListFormatter;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TopLevelNetworkEntryPreferenceController extends BasePreferenceController {
|
||||
|
||||
private final WifiMasterSwitchPreferenceController mWifiPreferenceController;
|
||||
private final MobileNetworkPreferenceController mMobileNetworkPreferenceController;
|
||||
private final TetherPreferenceController mTetherPreferenceController;
|
||||
|
||||
public TopLevelNetworkEntryPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mMobileNetworkPreferenceController = new MobileNetworkPreferenceController(mContext);
|
||||
mTetherPreferenceController = new TetherPreferenceController(
|
||||
mContext, null /* lifecycle */);
|
||||
mWifiPreferenceController = new WifiMasterSwitchPreferenceController(
|
||||
mContext, null /* metrics */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
final String wifiSummary = BidiFormatter.getInstance()
|
||||
.unicodeWrap(mContext.getString(R.string.wifi_settings_title));
|
||||
final String mobileSummary = mContext.getString(
|
||||
R.string.network_dashboard_summary_mobile);
|
||||
final String dataUsageSummary = mContext.getString(
|
||||
R.string.network_dashboard_summary_data_usage);
|
||||
final String hotspotSummary = mContext.getString(
|
||||
R.string.network_dashboard_summary_hotspot);
|
||||
|
||||
final List<String> summaries = new ArrayList<>();
|
||||
if (mWifiPreferenceController.isAvailable()
|
||||
&& !TextUtils.isEmpty(wifiSummary)) {
|
||||
summaries.add(wifiSummary);
|
||||
}
|
||||
if (mMobileNetworkPreferenceController.isAvailable() && !TextUtils.isEmpty(mobileSummary)) {
|
||||
summaries.add(mobileSummary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(dataUsageSummary)) {
|
||||
summaries.add(dataUsageSummary);
|
||||
}
|
||||
if (mTetherPreferenceController.isAvailable()
|
||||
&& !TextUtils.isEmpty(hotspotSummary)) {
|
||||
summaries.add(hotspotSummary);
|
||||
}
|
||||
return ListFormatter.getInstance().format(summaries);
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import com.android.settings.slices.SliceBuilderUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
public class ZenModeSliceBuilder {
|
||||
@@ -94,7 +95,7 @@ public class ZenModeSliceBuilder {
|
||||
|
||||
return new ListBuilder(context, ZEN_MODE_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.addEndItem(toggleSliceAction)
|
||||
.setPrimaryAction(primarySliceAction))
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -70,7 +71,7 @@ public class ConfirmDeviceCredentialActivity extends Activity {
|
||||
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
|
||||
boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
|
||||
|
||||
int userId = Utils.getCredentialOwnerUserId(this);
|
||||
int userId = UserHandle.myUserId();
|
||||
if (isInternalActivity()) {
|
||||
try {
|
||||
userId = Utils.getUserIdFromBundle(this, intent.getExtras());
|
||||
|
||||
@@ -125,8 +125,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
mCancelButton = (Button) view.findViewById(R.id.cancelButton);
|
||||
mFingerprintIcon = (ImageView) view.findViewById(R.id.fingerprintIcon);
|
||||
mFingerprintHelper = new FingerprintUiHelper(
|
||||
mFingerprintIcon,
|
||||
(TextView) view.findViewById(R.id.errorText), this, mEffectiveUserId);
|
||||
mFingerprintIcon, view.findViewById(R.id.errorText), this, mUserId);
|
||||
boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
|
||||
SHOW_CANCEL_BUTTON, false);
|
||||
boolean hasAlternateButton = mFrp && !TextUtils.isEmpty(mFrpAlternateButtonText);
|
||||
|
||||
@@ -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.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class TopLevelSecurityEntryPreferenceController extends BasePreferenceController {
|
||||
|
||||
public TopLevelSecurityEntryPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
final FingerprintManager fpm =
|
||||
Utils.getFingerprintManagerOrNull(mContext);
|
||||
final FaceManager faceManager =
|
||||
Utils.getFaceManagerOrNull(mContext);
|
||||
if (faceManager != null && faceManager.isHardwareDetected()) {
|
||||
return mContext.getText(R.string.security_dashboard_summary_face);
|
||||
} else if (fpm != null && fpm.isHardwareDetected()) {
|
||||
return mContext.getText(R.string.security_dashboard_summary);
|
||||
} else {
|
||||
return mContext.getText(R.string.security_dashboard_summary_no_fingerprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SettingsSlicesContract;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -47,12 +48,15 @@ import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.InputRangeBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
|
||||
@@ -250,11 +254,11 @@ public class SliceBuilderUtils {
|
||||
(TogglePreferenceController) controller;
|
||||
final SliceAction sliceAction = getToggleAction(context, sliceData,
|
||||
toggleController.isChecked());
|
||||
final List<String> keywords = buildSliceKeywords(sliceData);
|
||||
final Set<String> keywords = buildSliceKeywords(sliceData);
|
||||
|
||||
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(rowBuilder -> rowBuilder
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(sliceData.getTitle())
|
||||
.setSubtitle(subtitleText)
|
||||
.setPrimaryAction(
|
||||
@@ -270,11 +274,11 @@ public class SliceBuilderUtils {
|
||||
final IconCompat icon = getSafeIcon(context, sliceData);
|
||||
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
|
||||
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
|
||||
final List<String> keywords = buildSliceKeywords(sliceData);
|
||||
final Set<String> keywords = buildSliceKeywords(sliceData);
|
||||
|
||||
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(rowBuilder -> rowBuilder
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(sliceData.getTitle())
|
||||
.setSubtitle(subtitleText)
|
||||
.setPrimaryAction(
|
||||
@@ -293,11 +297,11 @@ public class SliceBuilderUtils {
|
||||
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
|
||||
final SliceAction primaryAction = new SliceAction(contentIntent, icon,
|
||||
sliceData.getTitle());
|
||||
final List<String> keywords = buildSliceKeywords(sliceData);
|
||||
final Set<String> keywords = buildSliceKeywords(sliceData);
|
||||
|
||||
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addInputRange(builder -> builder
|
||||
.addInputRange(new InputRangeBuilder()
|
||||
.setTitle(sliceData.getTitle())
|
||||
.setSubtitle(subtitleText)
|
||||
.setPrimaryAction(primaryAction)
|
||||
@@ -343,8 +347,8 @@ public class SliceBuilderUtils {
|
||||
|| TextUtils.equals(summary, doublePlaceHolder));
|
||||
}
|
||||
|
||||
private static List<String> buildSliceKeywords(SliceData data) {
|
||||
final List<String> keywords = new ArrayList<>();
|
||||
private static Set<String> buildSliceKeywords(SliceData data) {
|
||||
final Set<String> keywords = new ArraySet<>();
|
||||
|
||||
keywords.add(data.getTitle());
|
||||
|
||||
@@ -366,7 +370,7 @@ public class SliceBuilderUtils {
|
||||
|
||||
private static Slice buildUnavailableSlice(Context context, SliceData data) {
|
||||
final String title = data.getTitle();
|
||||
final List<String> keywords = buildSliceKeywords(data);
|
||||
final Set<String> keywords = buildSliceKeywords(data);
|
||||
@ColorInt final int color = Utils.getColorAccentDefaultColor(context);
|
||||
final CharSequence summary = context.getText(R.string.disabled_dependent_setting_summary);
|
||||
final IconCompat icon = IconCompat.createWithResource(context, data.getIconResource());
|
||||
@@ -375,9 +379,9 @@ public class SliceBuilderUtils {
|
||||
|
||||
return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(builder -> builder
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.setTitleItem(icon)
|
||||
.setTitleItem(icon, ListBuilder.SMALL_IMAGE)
|
||||
.setSubtitle(summary)
|
||||
.setPrimaryAction(primaryAction))
|
||||
.setKeywords(keywords)
|
||||
|
||||
@@ -14,20 +14,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard;
|
||||
package com.android.settings.widget;
|
||||
|
||||
import static androidx.annotation.VisibleForTesting.NONE;
|
||||
|
||||
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB;
|
||||
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
public class RoundedHomepageIcon extends LayerDrawable {
|
||||
|
||||
private static final String TAG = "RoundedHomepageIcon";
|
||||
@@ -36,7 +42,7 @@ public class RoundedHomepageIcon extends LayerDrawable {
|
||||
int mBackgroundColor = -1;
|
||||
|
||||
public RoundedHomepageIcon(Context context, Drawable foreground) {
|
||||
super(new Drawable[] {
|
||||
super(new Drawable[]{
|
||||
context.getDrawable(R.drawable.ic_homepage_generic_background),
|
||||
foreground
|
||||
});
|
||||
@@ -45,6 +51,33 @@ public class RoundedHomepageIcon extends LayerDrawable {
|
||||
setLayerInset(1 /* index */, insetPx, insetPx, insetPx, insetPx);
|
||||
}
|
||||
|
||||
public void setBackgroundColor(Context context, Tile tile) {
|
||||
final Bundle metaData = tile.getMetaData();
|
||||
try {
|
||||
if (metaData != null) {
|
||||
// Load from bg.argb first
|
||||
int bgColor = metaData.getInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB,
|
||||
0 /* default */);
|
||||
// Not found, load from bg.hint
|
||||
if (bgColor == 0) {
|
||||
final int colorRes = metaData.getInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
|
||||
0 /* default */);
|
||||
if (colorRes != 0) {
|
||||
bgColor = context.getPackageManager()
|
||||
.getResourcesForApplication(tile.getPackageName())
|
||||
.getColor(colorRes, null /* theme */);
|
||||
}
|
||||
}
|
||||
// If found anything, use it.
|
||||
if (bgColor != 0) {
|
||||
setBackgroundColor(bgColor);
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Failed to set background color for " + tile.getPackageName());
|
||||
}
|
||||
}
|
||||
|
||||
public void setBackgroundColor(int color) {
|
||||
mBackgroundColor = color;
|
||||
getDrawable(0).setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
|
||||
@@ -42,6 +42,7 @@ import com.android.settings.slices.SliceBuilderUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
/**
|
||||
@@ -95,7 +96,7 @@ public class WifiSliceBuilder {
|
||||
|
||||
return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY)
|
||||
.setAccentColor(color)
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.setSubtitle(summary)
|
||||
.addEndItem(toggleSliceAction)
|
||||
|
||||
@@ -209,7 +209,7 @@ public class WifiCallingSliceHelper {
|
||||
|
||||
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
|
||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(mContext.getText(R.string.wifi_calling_settings_title))
|
||||
.addEndItem(
|
||||
new SliceAction(
|
||||
@@ -298,7 +298,7 @@ public class WifiCallingSliceHelper {
|
||||
// Top row shows information on current preference state
|
||||
ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
|
||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
|
||||
listBuilder.setHeader(new ListBuilder.HeaderBuilder(listBuilder)
|
||||
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
|
||||
.setTitle(mContext.getText(R.string.wifi_calling_mode_title))
|
||||
.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref))
|
||||
.setPrimaryAction(new SliceAction(
|
||||
@@ -338,7 +338,7 @@ public class WifiCallingSliceHelper {
|
||||
int preferenceTitleResId, String action, boolean checked) {
|
||||
final IconCompat icon =
|
||||
IconCompat.createWithResource(mContext, R.drawable.radio_button_check);
|
||||
return new RowBuilder(listBuilder)
|
||||
return new RowBuilder()
|
||||
.setTitle(mContext.getText(preferenceTitleResId))
|
||||
.setTitleItem(new SliceAction(getBroadcastIntent(action),
|
||||
icon, mContext.getText(preferenceTitleResId), checked));
|
||||
@@ -488,7 +488,7 @@ public class WifiCallingSliceHelper {
|
||||
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
|
||||
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
|
||||
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
|
||||
.addRow(b -> b
|
||||
.addRow(new RowBuilder()
|
||||
.setTitle(title)
|
||||
.setSubtitle(subtitle)
|
||||
.setPrimaryAction(new SliceAction(
|
||||
|
||||
@@ -39,7 +39,6 @@ com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMi
|
||||
com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages
|
||||
com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment
|
||||
com.android.settings.fuelgauge.AdvancedPowerUsageDetail
|
||||
com.android.settings.fuelgauge.BatteryHistoryDetail
|
||||
com.android.settings.fuelgauge.InactiveApps
|
||||
com.android.settings.fuelgauge.RestrictedAppDetails
|
||||
com.android.settings.IccLockSettings
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<bool name="config_tintSettingIcon">false</bool>
|
||||
<bool name="config_enableColorTemperature">false</bool>
|
||||
<bool name="config_show_camera_laser_sensor">false</bool>
|
||||
<bool name="config_show_connectivity_monitor">false</bool>
|
||||
|
||||
@@ -40,10 +40,10 @@ import androidx.preference.Preference;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||
|
||||
@@ -55,23 +55,24 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
||||
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
|
||||
public class AccessibilityHearingAidPreferenceControllerTest {
|
||||
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
||||
private static final String TEST_DEVICE_NAME = "TEST_HEARING_AID_BT_DEVICE_NAME";
|
||||
private static final String HEARING_AID_PREFERENCE = "hearing_aid_preference";
|
||||
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private BluetoothManager mBluetoothManager;
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
private Context mContext;
|
||||
private Preference mHearingAidPreference;
|
||||
private List<Integer> mProfileSupportedList;
|
||||
private AccessibilityHearingAidPreferenceController mPreferenceController;
|
||||
|
||||
@Mock
|
||||
@@ -79,8 +80,6 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
@Mock
|
||||
private LocalBluetoothAdapter mLocalBluetoothAdapter;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
@Mock
|
||||
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
|
||||
@@ -161,7 +160,7 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
||||
@Test
|
||||
public void onNotSupportHearingAidProfile_doNotDoReceiverOperation() {
|
||||
//clear bluetooth supported profile
|
||||
mProfileSupportedList.clear();
|
||||
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext, HEARING_AID_PREFERENCE);
|
||||
mPreferenceController.setPreference(mHearingAidPreference);
|
||||
//not call registerReceiver()
|
||||
@@ -178,18 +177,17 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
||||
mLocalBluetoothManager = ShadowBluetoothUtils.getLocalBtManager(mContext);
|
||||
mBluetoothManager = new BluetoothManager(mContext);
|
||||
mBluetoothAdapter = mBluetoothManager.getAdapter();
|
||||
when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
|
||||
when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
|
||||
}
|
||||
|
||||
private void setupHearingAidEnvironment() {
|
||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
|
||||
mProfileSupportedList = new ArrayList<Integer>();
|
||||
mProfileSupportedList.add(BluetoothProfile.HEARING_AID);
|
||||
when(mLocalBluetoothAdapter.getSupportedProfiles()).thenReturn(mProfileSupportedList);
|
||||
mShadowBluetoothAdapter.enable();
|
||||
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
|
||||
when(mCachedBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME);
|
||||
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
|
||||
|
||||
@@ -15,40 +15,20 @@
|
||||
*/
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import static com.android.settings.accounts.AccountDashboardFragmentTest
|
||||
.ShadowAuthenticationHelper.LABELS;
|
||||
import static com.android.settings.accounts.AccountDashboardFragmentTest
|
||||
.ShadowAuthenticationHelper.TYPES;
|
||||
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.os.UserHandle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.testutils.Robolectric;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.Resetter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class AccountDashboardFragmentTest {
|
||||
|
||||
@@ -59,66 +39,11 @@ public class AccountDashboardFragmentTest {
|
||||
mFragment = new AccountDashboardFragment();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowAuthenticationHelper.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCategory_isAccount() {
|
||||
assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_ACCOUNT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {
|
||||
ShadowAuthenticationHelper.class
|
||||
})
|
||||
public void updateSummary_hasAccount_shouldDisplayUpTo3AccountTypes() {
|
||||
final SummaryLoader loader = mock(SummaryLoader.class);
|
||||
final FragmentActivity activity = Robolectric.buildActivity(
|
||||
FragmentActivity.class).setup().get();
|
||||
|
||||
final SummaryLoader.SummaryProvider provider =
|
||||
AccountDashboardFragment.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(activity,
|
||||
loader);
|
||||
provider.setListening(true);
|
||||
|
||||
verify(loader).setSummary(provider, LABELS[0] + ", " + LABELS[1] + ", and " + LABELS[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowAuthenticationHelper.class)
|
||||
public void updateSummary_noAccount_shouldDisplayDefaultSummary() {
|
||||
ShadowAuthenticationHelper.setEnabledAccount(null);
|
||||
final SummaryLoader loader = mock(SummaryLoader.class);
|
||||
final FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
|
||||
|
||||
final SummaryLoader.SummaryProvider provider =
|
||||
AccountDashboardFragment.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(activity,
|
||||
loader);
|
||||
provider.setListening(true);
|
||||
|
||||
verify(loader).setSummary(provider,
|
||||
activity.getString(R.string.account_dashboard_default_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowAuthenticationHelper.class)
|
||||
public void updateSummary_noAccountTypeLabel_shouldNotDisplayNullEntry() {
|
||||
final SummaryLoader loader = mock(SummaryLoader.class);
|
||||
final FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
|
||||
final String[] enabledAccounts = {TYPES[0], "unlabeled_account_type", TYPES[1]};
|
||||
ShadowAuthenticationHelper.setEnabledAccount(enabledAccounts);
|
||||
|
||||
final SummaryLoader.SummaryProvider provider =
|
||||
AccountDashboardFragment.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(activity,
|
||||
loader);
|
||||
provider.setListening(true);
|
||||
|
||||
// should only show the 2 accounts with labels
|
||||
verify(loader).setSummary(provider, LABELS[0] + " and " + LABELS[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchIndexProvider_shouldIndexResource() {
|
||||
final List<SearchIndexableResource> indexRes =
|
||||
@@ -129,43 +54,5 @@ public class AccountDashboardFragmentTest {
|
||||
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
|
||||
}
|
||||
|
||||
@Implements(AuthenticatorHelper.class)
|
||||
public static class ShadowAuthenticationHelper {
|
||||
|
||||
static final String[] TYPES = {"type1", "type2", "type3", "type4"};
|
||||
static final String[] LABELS = {"LABEL1", "LABEL2", "LABEL3", "LABEL4"};
|
||||
private static String[] sEnabledAccount = TYPES;
|
||||
|
||||
public void __constructor__(Context context, UserHandle userHandle,
|
||||
AuthenticatorHelper.OnAccountsUpdateListener listener) {
|
||||
}
|
||||
|
||||
private static void setEnabledAccount(String[] enabledAccount) {
|
||||
sEnabledAccount = enabledAccount;
|
||||
}
|
||||
|
||||
@Resetter
|
||||
public static void reset() {
|
||||
sEnabledAccount = TYPES;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public String[] getEnabledAccountTypes() {
|
||||
return sEnabledAccount;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public CharSequence getLabelForType(Context context, final String accountType) {
|
||||
if (TextUtils.equals(accountType, TYPES[0])) {
|
||||
return LABELS[0];
|
||||
} else if (TextUtils.equals(accountType, TYPES[1])) {
|
||||
return LABELS[1];
|
||||
} else if (TextUtils.equals(accountType, TYPES[2])) {
|
||||
return LABELS[2];
|
||||
} else if (TextUtils.equals(accountType, TYPES[3])) {
|
||||
return LABELS[3];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public class AccountDetailDashboardFragmentTest {
|
||||
|
||||
final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class);
|
||||
final Preference preference = new Preference(mContext);
|
||||
dashboardFeatureProvider.bindPreferenceToTile(activity,
|
||||
dashboardFeatureProvider.bindPreferenceToTile(activity, false /* forceRoundedIcon */,
|
||||
MetricsProto.MetricsEvent.DASHBOARD_SUMMARY, preference, tile, null /* key */,
|
||||
Preference.DEFAULT_ORDER);
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import static com.android.settings.accounts.TopLevelAccountEntryPreferenceControllerTest
|
||||
.ShadowAuthenticationHelper.LABELS;
|
||||
import static com.android.settings.accounts.TopLevelAccountEntryPreferenceControllerTest
|
||||
.ShadowAuthenticationHelper.TYPES;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.Resetter;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {TopLevelAccountEntryPreferenceControllerTest.ShadowAuthenticationHelper.class})
|
||||
public class TopLevelAccountEntryPreferenceControllerTest {
|
||||
|
||||
private TopLevelAccountEntryPreferenceController mController;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new TopLevelAccountEntryPreferenceController(mContext, "test_key");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowAuthenticationHelper.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
public void updateSummary_hasAccount_shouldDisplayUpTo3AccountTypes() {
|
||||
assertThat(mController.getSummary())
|
||||
.isEqualTo(LABELS[0] + ", " + LABELS[1] + ", and " + LABELS[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateSummary_noAccount_shouldDisplayDefaultSummary() {
|
||||
ShadowAuthenticationHelper.setEnabledAccount(null);
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo(
|
||||
mContext.getText(R.string.account_dashboard_default_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateSummary_noAccountTypeLabel_shouldNotDisplayNullEntry() {
|
||||
final String[] enabledAccounts = {TYPES[0], "unlabeled_account_type", TYPES[1]};
|
||||
ShadowAuthenticationHelper.setEnabledAccount(enabledAccounts);
|
||||
|
||||
|
||||
// should only show the 2 accounts with labels
|
||||
assertThat(mController.getSummary()).isEqualTo(LABELS[0] + " and " + LABELS[1]);
|
||||
}
|
||||
|
||||
@Implements(AuthenticatorHelper.class)
|
||||
public static class ShadowAuthenticationHelper {
|
||||
|
||||
static final String[] TYPES = {"type1", "type2", "type3", "type4"};
|
||||
static final String[] LABELS = {"LABEL1", "LABEL2", "LABEL3", "LABEL4"};
|
||||
private static String[] sEnabledAccount = TYPES;
|
||||
|
||||
public void __constructor__(Context context, UserHandle userHandle,
|
||||
AuthenticatorHelper.OnAccountsUpdateListener listener) {
|
||||
}
|
||||
|
||||
private static void setEnabledAccount(String[] enabledAccount) {
|
||||
sEnabledAccount = enabledAccount;
|
||||
}
|
||||
|
||||
@Resetter
|
||||
public static void reset() {
|
||||
sEnabledAccount = TYPES;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public String[] getEnabledAccountTypes() {
|
||||
return sEnabledAccount;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public CharSequence getLabelForType(Context context, final String accountType) {
|
||||
if (TextUtils.equals(accountType, TYPES[0])) {
|
||||
return LABELS[0];
|
||||
} else if (TextUtils.equals(accountType, TYPES[1])) {
|
||||
return LABELS[1];
|
||||
} else if (TextUtils.equals(accountType, TYPES[2])) {
|
||||
return LABELS[2];
|
||||
} else if (TextUtils.equals(accountType, TYPES[3])) {
|
||||
return LABELS[3];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,65 +17,196 @@
|
||||
package com.android.settings.applications.defaultapps;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.RuntimeEnvironment.application;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
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.testutils.shadow.ShadowProcess;
|
||||
import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
import com.android.settingslib.applications.DefaultAppInfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
SettingsShadowResources.SettingsShadowTheme.class,
|
||||
ShadowProcess.class,
|
||||
ShadowSecureSettings.class
|
||||
})
|
||||
public class DefaultAutofillPickerTest {
|
||||
|
||||
private static final String TEST_APP_KEY = "foo.bar/foo.bar.Baz";
|
||||
private static final String MAIN_APP_KEY = "main.foo.bar/foo.bar.Baz";
|
||||
private static final String MANAGED_APP_KEY = "managed.foo.bar/foo.bar.Baz";
|
||||
private static final int MANAGED_PROFILE_UID = 10;
|
||||
private static final int MAIN_PROFILE_UID = 0;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Activity mActivity;
|
||||
private FragmentActivity mActivity;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private AppOpsManager mAppOpsManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private DefaultAutofillPicker mPicker;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
FakeFeatureFactory.setupForTest();
|
||||
|
||||
Resources res = application.getResources();
|
||||
|
||||
when(mActivity.getApplicationContext()).thenReturn(mActivity);
|
||||
when(mActivity.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
|
||||
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mActivity.getTheme()).thenReturn(res.newTheme());
|
||||
when(mActivity.getResources()).thenReturn(res);
|
||||
|
||||
mPicker = spy(new DefaultAutofillPicker());
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
|
||||
doReturn(application.getApplicationContext()).when(mPicker).getContext();
|
||||
doReturn(mActivity).when(mPicker).getActivity();
|
||||
doReturn(res).when(mPicker).getResources();
|
||||
doReturn(mScreen).when(mPicker).getPreferenceScreen();
|
||||
|
||||
doNothing().when(mPicker).onCreatePreferences(any(), any());
|
||||
doNothing().when(mPicker).updateCandidates();
|
||||
|
||||
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
|
||||
|
||||
doReturn(RuntimeEnvironment.application).when(mPicker).getContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetDefaultAppKey_shouldUpdateDefaultAutoFill() {
|
||||
assertThat(mPicker.setDefaultKey(TEST_APP_KEY)).isTrue();
|
||||
assertThat(mPicker.getDefaultKey()).isEqualTo(TEST_APP_KEY);
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
|
||||
ReflectionHelpers.setField(
|
||||
mPicker, "mUserId", MAIN_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
assertThat(mPicker.setDefaultKey(MAIN_APP_KEY)).isTrue();
|
||||
ReflectionHelpers.setField(
|
||||
mPicker, "mUserId", MANAGED_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
assertThat(mPicker.setDefaultKey(MANAGED_APP_KEY)).isTrue();
|
||||
|
||||
ReflectionHelpers.setField(
|
||||
mPicker, "mUserId", MAIN_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
assertThat(mPicker.getDefaultKey()).isEqualTo(MAIN_APP_KEY);
|
||||
ReflectionHelpers.setField(
|
||||
mPicker, "mUserId", MANAGED_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
assertThat(mPicker.getDefaultKey()).isEqualTo(MANAGED_APP_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfirmationMessage_shouldNotBeNull() {
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
|
||||
final DefaultAppInfo info = mock(DefaultAppInfo.class);
|
||||
when(info.loadLabel()).thenReturn("test_app_name");
|
||||
assertThat(mPicker.getConfirmationMessage(info)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mUserId_shouldDeriveUidFromManagedCaller() {
|
||||
setupUserManager();
|
||||
setupCaller();
|
||||
ShadowProcess.setMyUid(MANAGED_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
mPicker.onCreate(null);
|
||||
|
||||
assertUserId(MANAGED_PROFILE_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mUserId_shouldDeriveUidFromMainCaller() {
|
||||
setupUserManager();
|
||||
setupCaller();
|
||||
ShadowProcess.setMyUid(MAIN_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
mPicker.onCreate(null);
|
||||
|
||||
assertUserId(MAIN_PROFILE_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mUserId_shouldDeriveUidFromManagedClick() {
|
||||
setupUserManager();
|
||||
setupClick(/* forWork= */ true);
|
||||
ShadowProcess.setMyUid(MAIN_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
mPicker.onCreate(null);
|
||||
|
||||
assertUserId(MANAGED_PROFILE_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mUserId_shouldDeriveUidFromMainClick() {
|
||||
setupUserManager();
|
||||
setupClick(/* forWork= */ false);
|
||||
ShadowProcess.setMyUid(MAIN_PROFILE_UID * UserHandle.PER_USER_RANGE);
|
||||
|
||||
mPicker.onAttach((Context) mActivity);
|
||||
mPicker.onCreate(null);
|
||||
|
||||
assertUserId(MAIN_PROFILE_UID);
|
||||
}
|
||||
|
||||
private void setupUserManager() {
|
||||
UserHandle mainUserHandle = new UserHandle(MAIN_PROFILE_UID);
|
||||
UserHandle managedUserHandle = new UserHandle(MANAGED_PROFILE_UID);
|
||||
UserInfo managedUserInfo = new UserInfo(
|
||||
MANAGED_PROFILE_UID, "managed", UserInfo.FLAG_MANAGED_PROFILE);
|
||||
when(mUserManager.getUserProfiles())
|
||||
.thenReturn(Arrays.asList(mainUserHandle, managedUserHandle));
|
||||
when(mUserManager.getUserInfo(MANAGED_PROFILE_UID))
|
||||
.thenReturn(managedUserInfo);
|
||||
when(mUserManager.getUserHandle()).thenReturn(MAIN_PROFILE_UID);
|
||||
}
|
||||
|
||||
private void setupCaller() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("package_name", "any package name");
|
||||
when(mActivity.getIntent()).thenReturn(intent);
|
||||
}
|
||||
|
||||
private void setupClick(boolean forWork) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean("for_work", forWork);
|
||||
doReturn(bundle).when(mPicker).getArguments();
|
||||
}
|
||||
|
||||
private void assertUserId(int userId) {
|
||||
assertThat((Integer) ReflectionHelpers.getField(mPicker, "mUserId"))
|
||||
.isEqualTo(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
@@ -31,6 +32,7 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.HeadsetProfile;
|
||||
@@ -44,12 +46,13 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowAudioManager.class})
|
||||
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class})
|
||||
public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@@ -73,12 +76,15 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
|
||||
private Collection<CachedBluetoothDevice> cachedDevices;
|
||||
private ShadowAudioManager mShadowAudioManager;
|
||||
private BluetoothDevicePreference mPreference;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mShadowAudioManager = ShadowAudioManager.getShadow();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
cachedDevices =
|
||||
|
||||
@@ -22,15 +22,19 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -40,10 +44,14 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowBluetoothAdapter.class})
|
||||
public class BluetoothDeviceUpdaterTest {
|
||||
|
||||
@Mock
|
||||
@@ -58,18 +66,26 @@ public class BluetoothDeviceUpdaterTest {
|
||||
private SettingsActivity mSettingsActivity;
|
||||
@Mock
|
||||
private LocalBluetoothManager mLocalManager;
|
||||
@Mock
|
||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||
|
||||
private Context mContext;
|
||||
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
||||
private BluetoothDevicePreference mPreference;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mCachedDevices.add(mCachedBluetoothDevice);
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
|
||||
|
||||
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false);
|
||||
mBluetoothDeviceUpdater =
|
||||
@@ -171,4 +187,38 @@ public class BluetoothDeviceUpdaterTest {
|
||||
// Shouldn't crash
|
||||
mBluetoothDeviceUpdater.unregisterCallback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceUpdate_bluetoothDisabled_doNothing() {
|
||||
mShadowBluetoothAdapter.setEnabled(false);
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
|
||||
verify(mDevicePreferenceCallback, never()).onDeviceAdded(any(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceUpdate_bluetoothEnabled_addPreference() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mBluetoothDeviceUpdater.forceUpdate();
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_bluetoothStateIsOn_forceUpdate() {
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceAdded(any(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_bluetoothStateIsOff_removeAllDevicesFromPreference() {
|
||||
mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
|
||||
|
||||
mBluetoothDeviceUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
|
||||
assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
@@ -32,6 +33,7 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
@@ -43,12 +45,13 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowAudioManager.class})
|
||||
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class})
|
||||
public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
@Mock
|
||||
private DashboardFragment mDashboardFragment;
|
||||
@@ -67,12 +70,15 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
private ConnectedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
|
||||
private Collection<CachedBluetoothDevice> cachedDevices;
|
||||
private ShadowAudioManager mShadowAudioManager;
|
||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mShadowAudioManager = ShadowAudioManager.getShadow();
|
||||
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
|
||||
mShadowBluetoothAdapter.setEnabled(true);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
doReturn(mContext).when(mDashboardFragment).getContext();
|
||||
cachedDevices =
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.connecteddevice;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
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;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class TopLevelConnectedDevicesPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private TopLevelConnectedDevicesPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new TopLevelConnectedDevicesPreferenceController(mContext, "test_key");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowAdvancedConnectedDeviceController.class)
|
||||
public void getSummary_shouldCallAdvancedConnectedDeviceController() {
|
||||
assertThat(mController.getSummary())
|
||||
.isEqualTo(mContext.getText(R.string.settings_label_launcher));
|
||||
}
|
||||
|
||||
@Implements(AdvancedConnectedDeviceController.class)
|
||||
private static class ShadowAdvancedConnectedDeviceController {
|
||||
|
||||
@Implementation
|
||||
public static int getConnectedDevicesSummaryResourceId(Context context) {
|
||||
return R.string.settings_label_launcher;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,14 +45,14 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.homepage.conditional.Condition;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionAdapter;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settings.widget.RoundedHomepageIcon;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
import com.android.settingslib.utils.IconCache;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -95,7 +95,6 @@ public class DashboardAdapterTest {
|
||||
mActivityInfo.packageName = "pkg";
|
||||
mActivityInfo.name = "class";
|
||||
mActivityInfo.metaData = new Bundle();
|
||||
when(mFactory.dashboardFeatureProvider.shouldTintIcon()).thenReturn(true);
|
||||
|
||||
when(mContext.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
@@ -115,7 +114,7 @@ public class DashboardAdapterTest {
|
||||
spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */,
|
||||
null /* lifecycle */));
|
||||
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3");
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1", "pkg2", "pkg3");
|
||||
adapter.setSuggestions(suggestions);
|
||||
|
||||
final RecyclerView data = mock(RecyclerView.class);
|
||||
@@ -147,7 +146,7 @@ public class DashboardAdapterTest {
|
||||
spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */,
|
||||
null /* lifecycle */));
|
||||
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
adapter.setSuggestions(suggestions);
|
||||
final DashboardData dashboardData = adapter.mDashboardData;
|
||||
reset(adapter); // clear interactions tracking
|
||||
@@ -164,7 +163,7 @@ public class DashboardAdapterTest {
|
||||
spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */,
|
||||
null /* lifecycle */));
|
||||
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
adapter.setSuggestions(suggestions);
|
||||
|
||||
reset(adapter); // clear interactions tracking
|
||||
@@ -178,7 +177,7 @@ public class DashboardAdapterTest {
|
||||
public void onBindSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
|
||||
mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
|
||||
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
|
||||
mDashboardAdapter.setSuggestions(suggestions);
|
||||
|
||||
@@ -243,55 +242,6 @@ public class DashboardAdapterTest {
|
||||
.isInstanceOf(RoundedHomepageIcon.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindTile_externalTileWithBackgroundColorRawValue_shouldUpdateIcon() {
|
||||
final Context context = spy(RuntimeEnvironment.application);
|
||||
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
|
||||
final DashboardAdapter.DashboardItemHolder holder =
|
||||
new DashboardAdapter.DashboardItemHolder(view);
|
||||
final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
|
||||
tile.getMetaData().putInt(DashboardAdapter.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB,
|
||||
0xff0000);
|
||||
doReturn(Icon.createWithResource(context, R.drawable.ic_settings))
|
||||
.when(tile).getIcon(context);
|
||||
final IconCache iconCache = new IconCache(context);
|
||||
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
|
||||
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
|
||||
|
||||
doReturn("another.package").when(context).getPackageName();
|
||||
mDashboardAdapter.onBindTile(holder, tile);
|
||||
|
||||
final RoundedHomepageIcon homepageIcon = (RoundedHomepageIcon) iconCache.getIcon(
|
||||
tile.getIcon(context));
|
||||
assertThat(homepageIcon.mBackgroundColor).isEqualTo(0xff0000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
|
||||
final Context context = spy(RuntimeEnvironment.application);
|
||||
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
|
||||
final DashboardAdapter.DashboardItemHolder holder =
|
||||
new DashboardAdapter.DashboardItemHolder(view);
|
||||
final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
|
||||
tile.getMetaData().putInt(TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
|
||||
R.color.memory_critical);
|
||||
doReturn(Icon.createWithResource(context, R.drawable.ic_settings))
|
||||
.when(tile).getIcon(context);
|
||||
final IconCache iconCache = new IconCache(context);
|
||||
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
|
||||
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
|
||||
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
|
||||
|
||||
doReturn("another.package").when(context).getPackageName();
|
||||
mDashboardAdapter.onBindTile(holder, tile);
|
||||
|
||||
final RoundedHomepageIcon homepageIcon = (RoundedHomepageIcon) iconCache.getIcon(
|
||||
tile.getIcon(context));
|
||||
assertThat(homepageIcon.mBackgroundColor)
|
||||
.isEqualTo(RuntimeEnvironment.application.getColor(R.color.memory_critical));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindTile_externalTile_usingRoundedHomepageIcon_shouldNotUpdateIcon() {
|
||||
final Context context = RuntimeEnvironment.application;
|
||||
@@ -315,7 +265,7 @@ public class DashboardAdapterTest {
|
||||
any(RoundedHomepageIcon.class));
|
||||
}
|
||||
|
||||
private List<Suggestion> makeSuggestionsV2(String... pkgNames) {
|
||||
private List<Suggestion> makeSuggestions(String... pkgNames) {
|
||||
final List<Suggestion> suggestions = new ArrayList<>();
|
||||
for (String pkgName : pkgNames) {
|
||||
final Suggestion suggestion = new Suggestion.Builder(pkgName)
|
||||
|
||||
@@ -33,8 +33,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListUpdateCallback;
|
||||
|
||||
import com.android.settings.dashboard.conditional.AirplaneModeCondition;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.homepage.conditional.AirplaneModeCondition;
|
||||
import com.android.settings.homepage.conditional.Condition;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
|
||||
@@ -49,7 +49,7 @@ import android.os.UserManager;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
@@ -59,7 +59,6 @@ import com.android.settings.testutils.shadow.ShadowTileUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.drawer.TileUtils;
|
||||
|
||||
@@ -88,19 +87,19 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private CategoryManager mCategoryManager;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
private Context mContext;
|
||||
private ActivityInfo mActivityInfo;
|
||||
private DashboardFeatureProviderImpl mImpl;
|
||||
private boolean mForceRoundedIcon;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mForceRoundedIcon = false;
|
||||
mActivityInfo = new ActivityInfo();
|
||||
mActivityInfo.packageName = "pkg";
|
||||
mActivityInfo.name = "class";
|
||||
@@ -127,7 +126,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
doReturn(Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565)))
|
||||
.when(tile).getIcon(any(Context.class));
|
||||
mActivityInfo.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI");
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getTitle()).isEqualTo(tile.title);
|
||||
@@ -144,7 +143,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getFragment()).isNull();
|
||||
@@ -163,7 +162,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
when(mActivity.getApplicationContext().getSystemService(Context.USER_SERVICE))
|
||||
.thenReturn(mUserManager);
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
preference.getOnPreferenceClickListener().onPreferenceClick(null);
|
||||
|
||||
@@ -180,14 +179,14 @@ public class DashboardFeatureProviderImplTest {
|
||||
when(mActivity.getSystemService(Context.USER_SERVICE))
|
||||
.thenReturn(mUserManager);
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
preference.getOnPreferenceClickListener().onPreferenceClick(null);
|
||||
|
||||
verify(mFeatureFactory.metricsFeatureProvider).logDashboardStartIntent(
|
||||
any(Context.class),
|
||||
any(Intent.class),
|
||||
eq(MetricsProto.MetricsEvent.SETTINGS_GESTURES));
|
||||
eq(MetricsEvent.SETTINGS_GESTURES));
|
||||
verify(mActivity)
|
||||
.startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
|
||||
}
|
||||
@@ -205,7 +204,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
when(mActivity.getApplicationContext().getPackageName())
|
||||
.thenReturn(RuntimeEnvironment.application.getPackageName());
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
preference.getOnPreferenceClickListener().onPreferenceClick(null);
|
||||
verify(mFeatureFactory.metricsFeatureProvider).logDashboardStartIntent(
|
||||
@@ -219,7 +218,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
@Test
|
||||
public void bindPreference_nullPreference_shouldIgnore() {
|
||||
final Tile tile = mock(Tile.class);
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
null, tile, "123", Preference.DEFAULT_ORDER);
|
||||
|
||||
verifyZeroInteractions(tile);
|
||||
@@ -229,7 +228,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, null /*key */, Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getKey()).isNotNull();
|
||||
@@ -240,7 +239,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
public void bindPreference_noSummary_shouldSetSummaryToPlaceholder() {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, null /*key */, Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getSummary())
|
||||
@@ -252,7 +251,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
tile.summary = "test";
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, null /*key */, Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getSummary()).isEqualTo(tile.summary);
|
||||
@@ -266,7 +265,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI,
|
||||
"content://com.android.settings/tile_summary");
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, null /*key */, Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getSummary()).isEqualTo(ShadowTileUtils.MOCK_SUMMARY);
|
||||
@@ -277,7 +276,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
final Preference preference = new Preference(RuntimeEnvironment.application);
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, null /* key */, Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getKey()).isEqualTo(tile.getKey(mContext));
|
||||
@@ -292,7 +291,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI,
|
||||
"content://com.android.settings/tile_icon");
|
||||
mImpl.bindIcon(preference, tile);
|
||||
mImpl.bindIcon(preference, tile, false /* forceRoundedIcon */);
|
||||
|
||||
assertThat(preference.getIcon()).isNotNull();
|
||||
}
|
||||
@@ -304,7 +303,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, "123", baseOrder);
|
||||
|
||||
assertThat(preference.getOrder()).isEqualTo(tile.getOrder() + baseOrder);
|
||||
@@ -317,7 +316,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10);
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, testOrder);
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getOrder()).isEqualTo(testOrder);
|
||||
@@ -329,7 +328,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
mActivityInfo.metaData.putString(META_DATA_KEY_ORDER, "hello");
|
||||
|
||||
mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
|
||||
mImpl.bindPreferenceToTile(mActivity, mForceRoundedIcon, MetricsEvent.VIEW_UNKNOWN,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
|
||||
assertThat(preference.getOrder()).isEqualTo(Preference.DEFAULT_ORDER);
|
||||
@@ -343,7 +342,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key");
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
tile.userHandle = null;
|
||||
mImpl.bindPreferenceToTile(activity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(activity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
preference.performClick();
|
||||
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
|
||||
@@ -352,7 +351,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
assertThat(launchIntent.getAction())
|
||||
.isEqualTo("TestAction");
|
||||
assertThat(launchIntent.getIntExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY, 0))
|
||||
.isEqualTo(MetricsProto.MetricsEvent.SETTINGS_GESTURES);
|
||||
.isEqualTo(MetricsEvent.SETTINGS_GESTURES);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -367,7 +366,7 @@ public class DashboardFeatureProviderImplTest {
|
||||
mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction");
|
||||
tile.userHandle = null;
|
||||
|
||||
mImpl.bindPreferenceToTile(activity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
mImpl.bindPreferenceToTile(activity, mForceRoundedIcon, MetricsEvent.SETTINGS_GESTURES,
|
||||
preference, tile, "123", Preference.DEFAULT_ORDER);
|
||||
preference.performClick();
|
||||
|
||||
@@ -377,63 +376,11 @@ public class DashboardFeatureProviderImplTest {
|
||||
assertThat(launchIntent).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferences_noCategory_shouldReturnNull() {
|
||||
mImpl = new DashboardFeatureProviderImpl(mActivity);
|
||||
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
|
||||
when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
|
||||
.thenReturn(null);
|
||||
|
||||
assertThat(mImpl.getPreferencesForCategory(null, null,
|
||||
MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferences_noTileForCategory_shouldReturnNull() {
|
||||
mImpl = new DashboardFeatureProviderImpl(mActivity);
|
||||
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
|
||||
when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
|
||||
.thenReturn(new DashboardCategory(CategoryKey.CATEGORY_HOMEPAGE));
|
||||
|
||||
assertThat(mImpl.getPreferencesForCategory(null, null,
|
||||
MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPreferences_hasTileForCategory_shouldReturnPrefList() {
|
||||
mImpl = new DashboardFeatureProviderImpl(mActivity);
|
||||
ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
|
||||
final DashboardCategory category = new DashboardCategory(CategoryKey.CATEGORY_HOMEPAGE);
|
||||
category.addTile(new Tile(mActivityInfo, category.key));
|
||||
when(mCategoryManager
|
||||
.getTilesByCategory(any(Context.class), eq(CategoryKey.CATEGORY_HOMEPAGE)))
|
||||
.thenReturn(category);
|
||||
|
||||
assertThat(mImpl.getPreferencesForCategory(mActivity,
|
||||
ShadowApplication.getInstance().getApplicationContext(),
|
||||
MetricsProto.MetricsEvent.SETTINGS_GESTURES,
|
||||
CategoryKey.CATEGORY_HOMEPAGE).isEmpty())
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetExtraIntentAction_shouldReturnNull() {
|
||||
assertThat(mImpl.getExtraIntentAction()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldTintIcon_enabledInResources_shouldBeTrue() {
|
||||
assertThat(mImpl.shouldTintIcon()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void testShouldTintIcon_disabledInResources_shouldBeFalse() {
|
||||
assertThat(mImpl.shouldTintIcon()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openTileIntent_profileSelectionDialog_shouldShow() {
|
||||
final Tile tile = new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.dashboard;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class DashboardFragmentRegistryTest {
|
||||
@Test
|
||||
public void pageAndKeyShouldHave1to1Mapping() {
|
||||
assertThat(DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP.size())
|
||||
.isEqualTo(DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP.size());
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,8 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.dashboard.conditional.ConditionManager;
|
||||
import com.android.settings.dashboard.conditional.FocusRecyclerView;
|
||||
import com.android.settings.homepage.conditional.ConditionManager;
|
||||
import com.android.settings.homepage.conditional.FocusRecyclerView;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.drawer.CategoryKey;
|
||||
|
||||
@@ -355,7 +355,7 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
mActivity, null, null, null);
|
||||
|
||||
final SubscriptionInfo subInfo = new SubscriptionInfo(0, "123456", 0, "name", "carrier",
|
||||
0, 0, "number", 0, null, "123", "456", "ZX");
|
||||
0, 0, "number", 0, null, "123", "456", "ZX", false, null, null);
|
||||
when(mSubscriptionManager.getDefaultDataSubscriptionInfo()).thenReturn(subInfo);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.settings.deviceinfo;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -25,14 +24,9 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import android.content.Intent;
|
||||
import android.icu.text.NumberFormat;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.text.format.Formatter;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
|
||||
|
||||
@@ -41,8 +35,6 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -65,34 +57,6 @@ public class StorageSettingsTest {
|
||||
when(mStorageManagerVolumeProvider.getVolumes()).thenReturn(mVolumes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateSummary_shouldDisplayUsedPercentAndFreeSpace() throws Exception {
|
||||
final SummaryLoader loader = mock(SummaryLoader.class);
|
||||
final SummaryLoader.SummaryProvider provider =
|
||||
StorageSettings.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(mActivity, loader);
|
||||
final VolumeInfo volumeInfo = mVolumes.get(0);
|
||||
when(volumeInfo.isMountedReadable()).thenReturn(true);
|
||||
when(volumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
|
||||
when(mStorageManagerVolumeProvider
|
||||
.getTotalBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
|
||||
.thenReturn(500L);
|
||||
when(mStorageManagerVolumeProvider
|
||||
.getFreeBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
|
||||
.thenReturn(0L);
|
||||
|
||||
ReflectionHelpers
|
||||
.setField(provider, "mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
|
||||
ReflectionHelpers.setField(provider, "mContext", RuntimeEnvironment.application);
|
||||
|
||||
provider.setListening(true);
|
||||
|
||||
final String percentage = NumberFormat.getPercentInstance().format(1);
|
||||
final String freeSpace = Formatter.formatFileSize(RuntimeEnvironment.application, 0);
|
||||
verify(loader).setSummary(provider,
|
||||
RuntimeEnvironment.application.getString(
|
||||
R.string.storage_summary, percentage, freeSpace));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlePublicVolumeClick_startsANonNullActivityWhenVolumeHasNoBrowse() {
|
||||
VolumeInfo volumeInfo = mock(VolumeInfo.class, RETURNS_DEEP_STUBS);
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.deviceinfo;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.icu.text.NumberFormat;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.text.format.Formatter;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class TopLevelStoragePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private StorageManagerVolumeProvider mStorageManagerVolumeProvider;
|
||||
|
||||
private Context mContext;
|
||||
private TopLevelStoragePreferenceController mController;
|
||||
private List<VolumeInfo> mVolumes;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mVolumes = new ArrayList<>();
|
||||
mVolumes.add(mock(VolumeInfo.class, RETURNS_DEEP_STUBS));
|
||||
when(mStorageManagerVolumeProvider.getVolumes()).thenReturn(mVolumes);
|
||||
|
||||
mController = new TopLevelStoragePreferenceController(mContext, "test_key");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateSummary_shouldDisplayUsedPercentAndFreeSpace() throws Exception {
|
||||
final VolumeInfo volumeInfo = mVolumes.get(0);
|
||||
when(volumeInfo.isMountedReadable()).thenReturn(true);
|
||||
when(volumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
|
||||
when(mStorageManagerVolumeProvider
|
||||
.getTotalBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
|
||||
.thenReturn(500L);
|
||||
when(mStorageManagerVolumeProvider
|
||||
.getFreeBytes(nullable(StorageStatsManager.class), nullable(VolumeInfo.class)))
|
||||
.thenReturn(0L);
|
||||
|
||||
ReflectionHelpers.setField(mController,
|
||||
"mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
|
||||
|
||||
final String percentage = NumberFormat.getPercentInstance().format(1);
|
||||
final String freeSpace = Formatter.formatFileSize(RuntimeEnvironment.application, 0);
|
||||
assertThat(mController.getSummary()).isEqualTo(
|
||||
RuntimeEnvironment.application.getString(
|
||||
R.string.storage_summary, percentage, freeSpace));
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,6 @@ public class BatterySaverControllerTest {
|
||||
mBatterySaverController = spy(new BatterySaverController(mContext));
|
||||
ReflectionHelpers.setField(mBatterySaverController, "mPowerManager", mPowerManager);
|
||||
ReflectionHelpers.setField(mBatterySaverController, "mBatterySaverPref", mBatterySaverPref);
|
||||
doNothing().when(mBatterySaverController).refreshConditionManager();
|
||||
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADVANCED_BATTERY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
@@ -40,6 +42,8 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.loader.app.LoaderManager;
|
||||
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.R;
|
||||
@@ -50,7 +54,6 @@ 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.core.AbstractPreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@@ -69,8 +72,6 @@ import org.robolectric.annotation.Config;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.loader.app.LoaderManager;
|
||||
|
||||
// TODO: Improve this test class so that it starts up the real activity and fragment.
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
@@ -343,18 +344,6 @@ public class PowerUsageSummaryTest {
|
||||
verify(mFragment).restartBatteryTipLoader();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_returnsCorrectLabel() {
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.batteryPercentString = "3%";
|
||||
assertThat(PowerUsageSummary.getDashboardLabel(mRealContext, info))
|
||||
.isEqualTo(info.batteryPercentString);
|
||||
|
||||
info.remainingLabel = "Phone will shut down soon";
|
||||
assertThat(PowerUsageSummary.getDashboardLabel(mRealContext, info))
|
||||
.isEqualTo("3% - Phone will shut down soon");
|
||||
}
|
||||
|
||||
public static class TestFragment extends PowerUsageSummary {
|
||||
private Context mContext;
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.fuelgauge;
|
||||
|
||||
import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel;
|
||||
|
||||
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 TopLevelBatteryPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_returnsCorrectLabel() {
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.batteryPercentString = "3%";
|
||||
assertThat(getDashboardLabel(mContext, info))
|
||||
.isEqualTo(info.batteryPercentString);
|
||||
|
||||
info.remainingLabel = "Phone will shut down soon";
|
||||
assertThat(getDashboardLabel(mContext, info))
|
||||
.isEqualTo("3% - Phone will shut down soon");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class CardContentProviderTest {
|
||||
|
||||
private Context mContext;
|
||||
private CardContentProvider mProvider;
|
||||
private Uri mUri;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
|
||||
mUri = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(CardContentProvider.CARD_AUTHORITY)
|
||||
.path(CardDatabaseHelper.CARD_TABLE)
|
||||
.build();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
CardDatabaseHelper.getInstance(mContext).close();
|
||||
CardDatabaseHelper.sCardDatabaseHelper = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cardData_insert() {
|
||||
final int cnt_before_instert = getRowCount();
|
||||
mContext.getContentResolver().insert(mUri, insertOneRow());
|
||||
final int cnt_after_instert = getRowCount();
|
||||
|
||||
assertThat(cnt_after_instert - cnt_before_instert).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cardData_query() {
|
||||
mContext.getContentResolver().insert(mUri, insertOneRow());
|
||||
final int count = getRowCount();
|
||||
|
||||
assertThat(count).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cardData_delete() {
|
||||
final ContentResolver contentResolver = mContext.getContentResolver();
|
||||
contentResolver.insert(mUri, insertOneRow());
|
||||
final int del_count = contentResolver.delete(mUri, null, null);
|
||||
|
||||
assertThat(del_count).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cardData_update() {
|
||||
final ContentResolver contentResolver = mContext.getContentResolver();
|
||||
contentResolver.insert(mUri, insertOneRow());
|
||||
|
||||
final double updatingScore= 0.87;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardDatabaseHelper.CardColumns.SCORE, updatingScore);
|
||||
final String strWhere = CardDatabaseHelper.CardColumns.NAME + "=?";
|
||||
final String[] selectionArgs = {"auto_rotate"};
|
||||
final int update_count = contentResolver.update(mUri, values, strWhere, selectionArgs);
|
||||
|
||||
assertThat(update_count).isGreaterThan(0);
|
||||
|
||||
final String[] columns = {CardDatabaseHelper.CardColumns.SCORE};
|
||||
final Cursor cr = contentResolver.query(mUri, columns, strWhere, selectionArgs, null);
|
||||
cr.moveToFirst();
|
||||
final double qryScore = cr.getDouble(0);
|
||||
|
||||
cr.close();
|
||||
assertThat(qryScore).isEqualTo(updatingScore);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void getType_shouldCrash() {
|
||||
mProvider.getType(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void invalid_Uri_shouldCrash() {
|
||||
final Uri invalid_Uri = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(CardContentProvider.CARD_AUTHORITY)
|
||||
.path("Invalid_table")
|
||||
.build();
|
||||
|
||||
mProvider.getTableFromMatch(invalid_Uri);
|
||||
}
|
||||
|
||||
private ContentValues insertOneRow() {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardDatabaseHelper.CardColumns.NAME, "auto_rotate");
|
||||
values.put(CardDatabaseHelper.CardColumns.TYPE, 0);
|
||||
values.put(CardDatabaseHelper.CardColumns.SCORE, 0.9);
|
||||
values.put(CardDatabaseHelper.CardColumns.SLICE_URI,
|
||||
"content://com.android.settings.slices/action/auto_rotate");
|
||||
values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2);
|
||||
values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings");
|
||||
values.put(CardDatabaseHelper.CardColumns.APP_VERSION, "1.0.0");
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private int getRowCount() {
|
||||
final ContentResolver contentResolver = mContext.getContentResolver();
|
||||
final Cursor cr = contentResolver.query(mUri, null, null, null);
|
||||
final int count = cr.getCount();
|
||||
cr.close();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class CardDatabaseHelperTest {
|
||||
|
||||
private Context mContext;
|
||||
private CardDatabaseHelper mCardDatabaseHelper;
|
||||
private SQLiteDatabase mDatabase;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mCardDatabaseHelper = CardDatabaseHelper.getInstance(mContext);
|
||||
mDatabase = mCardDatabaseHelper.getWritableDatabase();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
CardDatabaseHelper.getInstance(mContext).close();
|
||||
CardDatabaseHelper.sCardDatabaseHelper = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDatabaseSchema() {
|
||||
final Cursor cursor = mDatabase.rawQuery("SELECT * FROM " + CardDatabaseHelper.CARD_TABLE,
|
||||
null);
|
||||
final String[] columnNames = cursor.getColumnNames();
|
||||
|
||||
final String[] expectedNames = {
|
||||
CardDatabaseHelper.CardColumns.NAME,
|
||||
CardDatabaseHelper.CardColumns.TYPE,
|
||||
CardDatabaseHelper.CardColumns.SCORE,
|
||||
CardDatabaseHelper.CardColumns.SLICE_URI,
|
||||
CardDatabaseHelper.CardColumns.CATEGORY,
|
||||
CardDatabaseHelper.CardColumns.AVAILABILITY_URI,
|
||||
CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE,
|
||||
CardDatabaseHelper.CardColumns.PACKAGE_NAME,
|
||||
CardDatabaseHelper.CardColumns.APP_VERSION,
|
||||
CardDatabaseHelper.CardColumns.TITLE_RES_NAME,
|
||||
CardDatabaseHelper.CardColumns.TITLE_TEXT,
|
||||
CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME,
|
||||
CardDatabaseHelper.CardColumns.SUMMARY_TEXT,
|
||||
CardDatabaseHelper.CardColumns.ICON_RES_NAME,
|
||||
CardDatabaseHelper.CardColumns.ICON_RES_ID,
|
||||
CardDatabaseHelper.CardColumns.CARD_ACTION,
|
||||
CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS,
|
||||
};
|
||||
|
||||
assertThat(columnNames).isEqualTo(expectedNames);
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user