Snap for 10052121 from e0a4a343c4
to udc-release
Change-Id: Ifed9e4466a4fcde3a716eb18bdc77d2e9eca0634
This commit is contained in:
@@ -17,6 +17,6 @@
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/colorAccentPrimary"/>
|
||||
<item android:color="?androidprv:attr/materialColorSurfaceContainer"/>
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorPrimaryContainer"/>
|
||||
<item android:color="?androidprv:attr/materialColorSurfaceBright"/>
|
||||
</selector>
|
@@ -17,6 +17,6 @@
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorOnPrimary"/>
|
||||
<item android:color="?androidprv:attr/materialColorPrimaryContainer"/>
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorOnPrimaryContainer"/>
|
||||
<item android:color="?androidprv:attr/materialColorPrimary"/>
|
||||
</selector>
|
22
res/color/dream_card_summary_color_state_list.xml
Normal file
22
res/color/dream_card_summary_color_state_list.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorOnPrimaryContainer"/>
|
||||
<item android:color="?androidprv:attr/materialColorOnSurfaceVariant"/>
|
||||
</selector>
|
@@ -17,6 +17,6 @@
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorOnPrimary"/>
|
||||
<item android:color="?android:attr/textColorPrimary"/>
|
||||
<item android:state_selected="true" android:color="?androidprv:attr/materialColorOnPrimaryContainer"/>
|
||||
<item android:color="?androidprv:attr/materialColorOnSurface"/>
|
||||
</selector>
|
@@ -15,10 +15,11 @@
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="?android:attr/textColorSecondary"
|
||||
<path android:fillColor="?androidprv:attr/materialColorOnSurfaceVariant"
|
||||
android:pathData="M3,19Q2.175,19 1.588,18.413Q1,17.825 1,17V7Q1,6.175 1.588,5.588Q2.175,5 3,5H13Q13.825,5 14.413,5.588Q15,6.175 15,7V17Q15,17.825 14.413,18.413Q13.825,19 13,19ZM3,17H13Q13,17 13,17Q13,17 13,17V7Q13,7 13,7Q13,7 13,7H3Q3,7 3,7Q3,7 3,7V17Q3,17 3,17Q3,17 3,17ZM17,19V5H19V19ZM21,19V5H23V19ZM4,15H12L9.4,11.5L7.5,14L6.1,12.15ZM3,7Q3,7 3,7Q3,7 3,7V17Q3,17 3,17Q3,17 3,17Q3,17 3,17Q3,17 3,17V7Q3,7 3,7Q3,7 3,7Z"/>
|
||||
</vector>
|
@@ -17,6 +17,6 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?androidprv:attr/materialColorSurfaceBright" />
|
||||
<solid android:color="?androidprv:attr/materialColorSurfaceContainer" />
|
||||
<corners android:radius="@dimen/dream_item_corner_radius"/>
|
||||
</shape>
|
@@ -93,7 +93,7 @@
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:textSize="@dimen/dream_item_summary_text_size"
|
||||
android:textColor="@color/dream_card_text_color_state_list"
|
||||
android:textColor="@color/dream_card_summary_color_state_list"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@@ -17,17 +17,16 @@
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/dream_preview_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/dream_preview_button_title"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?android:attr/textColorPrimaryInverse"
|
||||
android:textColor="@color/settingslib_btn_colored_text_material"
|
||||
android:theme="@style/Theme.CollapsingToolbar.Settings"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_gravity="bottom|center"
|
||||
app:backgroundTint="?androidprv:attr/materialColorPrimaryContainer"
|
||||
app:iconTint="?android:attr/textColorPrimaryInverse"
|
||||
app:backgroundTint="@color/settingslib_btn_colored_background_material"
|
||||
app:iconTint="@color/settingslib_btn_colored_text_material"
|
||||
app:icon="@drawable/dream_preview_icon"/>
|
||||
|
@@ -283,7 +283,9 @@ public class FingerprintSettings extends SubSettings {
|
||||
case MSG_REFRESH_FINGERPRINT_TEMPLATES:
|
||||
removeFingerprintPreference(msg.arg1);
|
||||
updateAddPreference();
|
||||
updateFingerprintUnlockCategoryVisibility();
|
||||
if (isSfps()) {
|
||||
updateFingerprintUnlockCategoryVisibility();
|
||||
}
|
||||
updatePreferences();
|
||||
break;
|
||||
case MSG_FINGER_AUTH_SUCCESS:
|
||||
@@ -494,9 +496,13 @@ public class FingerprintSettings extends SubSettings {
|
||||
}
|
||||
|
||||
private boolean isSfps() {
|
||||
for (FingerprintSensorPropertiesInternal prop : mSensorProperties) {
|
||||
if (prop.isAnySidefpsType()) {
|
||||
return true;
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(getActivity());
|
||||
if (mFingerprintManager != null) {
|
||||
mSensorProperties = mFingerprintManager.getSensorPropertiesInternal();
|
||||
for (FingerprintSensorPropertiesInternal prop : mSensorProperties) {
|
||||
if (prop.isAnySidefpsType()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -838,18 +844,20 @@ public class FingerprintSettings extends SubSettings {
|
||||
|
||||
private List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mFingerprintUnlockCategoryPreferenceController =
|
||||
if (isSfps()) {
|
||||
mFingerprintUnlockCategoryPreferenceController =
|
||||
new FingerprintUnlockCategoryController(
|
||||
context,
|
||||
KEY_FINGERPRINT_UNLOCK_CATEGORY
|
||||
context,
|
||||
KEY_FINGERPRINT_UNLOCK_CATEGORY
|
||||
);
|
||||
mRequireScreenOnToAuthPreferenceController =
|
||||
new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
|
||||
context,
|
||||
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
||||
);
|
||||
controllers.add(mFingerprintUnlockCategoryPreferenceController);
|
||||
controllers.add(mRequireScreenOnToAuthPreferenceController);
|
||||
mRequireScreenOnToAuthPreferenceController =
|
||||
new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
|
||||
context,
|
||||
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
||||
);
|
||||
controllers.add(mFingerprintUnlockCategoryPreferenceController);
|
||||
controllers.add(mRequireScreenOnToAuthPreferenceController);
|
||||
}
|
||||
return controllers;
|
||||
}
|
||||
|
||||
|
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.datausage;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.widget.Switch;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.applications.AppStateBaseBridge.Callback;
|
||||
import com.android.settings.datausage.DataSaverBackend.Listener;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settingslib.applications.ApplicationsState.Callbacks;
|
||||
import com.android.settingslib.applications.ApplicationsState.Session;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@SearchIndexable
|
||||
public class DataSaverSummary extends SettingsPreferenceFragment
|
||||
implements OnMainSwitchChangeListener, Listener, Callback, Callbacks {
|
||||
|
||||
private static final String KEY_UNRESTRICTED_ACCESS = "unrestricted_access";
|
||||
|
||||
private SettingsMainSwitchBar mSwitchBar;
|
||||
private DataSaverBackend mDataSaverBackend;
|
||||
private Preference mUnrestrictedAccess;
|
||||
private ApplicationsState mApplicationsState;
|
||||
private AppStateDataUsageBridge mDataUsageBridge;
|
||||
private Session mSession;
|
||||
|
||||
// Flag used to avoid infinite loop due if user switch it on/off too quicky.
|
||||
private boolean mSwitching;
|
||||
|
||||
private Runnable mLoadAppRunnable = () -> {
|
||||
mApplicationsState = ApplicationsState.getInstance(
|
||||
(Application) getContext().getApplicationContext());
|
||||
mDataUsageBridge = new AppStateDataUsageBridge(mApplicationsState, this, mDataSaverBackend);
|
||||
mSession = mApplicationsState.newSession(this, getSettingsLifecycle());
|
||||
mDataUsageBridge.resume(true /* forceLoadAllApps */);
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
if (!isDataSaverVisible(getContext())) {
|
||||
finishFragment();
|
||||
return;
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.data_saver);
|
||||
mUnrestrictedAccess = findPreference(KEY_UNRESTRICTED_ACCESS);
|
||||
mDataSaverBackend = new DataSaverBackend(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
|
||||
mSwitchBar.setTitle(getContext().getString(R.string.data_saver_switch_title));
|
||||
mSwitchBar.show();
|
||||
mSwitchBar.addOnSwitchChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mDataSaverBackend.refreshAllowlist();
|
||||
mDataSaverBackend.refreshDenylist();
|
||||
mDataSaverBackend.addListener(this);
|
||||
if (mDataUsageBridge != null) {
|
||||
mDataUsageBridge.resume(true /* forceLoadAllApps */);
|
||||
} else {
|
||||
getView().post(mLoadAppRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mDataSaverBackend.remListener(this);
|
||||
if (mDataUsageBridge != null) {
|
||||
mDataUsageBridge.pause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
synchronized (this) {
|
||||
if (mSwitching) {
|
||||
return;
|
||||
}
|
||||
mSwitching = true;
|
||||
mDataSaverBackend.setDataSaverEnabled(isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.DATA_SAVER_SUMMARY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
return R.string.help_url_data_saver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataSaverChanged(boolean isDataSaving) {
|
||||
synchronized (this) {
|
||||
mSwitchBar.setChecked(isDataSaving);
|
||||
mSwitching = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllowlistStatusChanged(int uid, boolean isAllowlisted) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDenylistStatusChanged(int uid, boolean isDenylisted) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtraInfoUpdated() {
|
||||
updateUnrestrictedAccessSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningStateChanged(boolean running) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebuildComplete(ArrayList<AppEntry> apps) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageIconChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageSizeChanged(String packageName) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllSizesComputed() {
|
||||
updateUnrestrictedAccessSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLauncherInfoChanged() {
|
||||
updateUnrestrictedAccessSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
|
||||
}
|
||||
|
||||
private void updateUnrestrictedAccessSummary() {
|
||||
if (!isAdded() || isFinishingOrDestroyed() || mSession == null) return;
|
||||
|
||||
int count = 0;
|
||||
for (AppEntry entry : mSession.getAllApps()) {
|
||||
if (!ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry)) {
|
||||
continue;
|
||||
}
|
||||
if (entry.extraInfo != null && ((AppStateDataUsageBridge.DataUsageState)
|
||||
entry.extraInfo).isDataSaverAllowlisted) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
MessageFormat msgFormat = new MessageFormat(
|
||||
getResources().getString(R.string.data_saver_unrestricted_summary),
|
||||
Locale.getDefault());
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", count);
|
||||
mUnrestrictedAccess.setSummary(msgFormat.format(arguments));
|
||||
}
|
||||
|
||||
public static boolean isDataSaverVisible(Context context) {
|
||||
return context.getResources()
|
||||
.getBoolean(R.bool.config_show_data_saver);
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.data_saver) {
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return isDataSaverVisible(context)
|
||||
&& DataUsageUtils.hasMobileData(context)
|
||||
&& DataUsageUtils.getDefaultSubscriptionId(context)
|
||||
!= SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
}
|
||||
};
|
||||
}
|
176
src/com/android/settings/datausage/DataSaverSummary.kt
Normal file
176
src/com/android/settings/datausage/DataSaverSummary.kt
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.datausage
|
||||
|
||||
import android.app.Application
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.widget.Switch
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.R
|
||||
import com.android.settings.SettingsActivity
|
||||
import com.android.settings.SettingsPreferenceFragment
|
||||
import com.android.settings.applications.AppStateBaseBridge
|
||||
import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState
|
||||
import com.android.settings.search.BaseSearchIndexProvider
|
||||
import com.android.settings.widget.SettingsMainSwitchBar
|
||||
import com.android.settingslib.applications.ApplicationsState
|
||||
import com.android.settingslib.search.SearchIndexable
|
||||
import com.android.settingslib.spa.framework.util.formatString
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SearchIndexable
|
||||
class DataSaverSummary : SettingsPreferenceFragment() {
|
||||
private lateinit var switchBar: SettingsMainSwitchBar
|
||||
private lateinit var dataSaverBackend: DataSaverBackend
|
||||
private lateinit var unrestrictedAccess: Preference
|
||||
private var dataUsageBridge: AppStateDataUsageBridge? = null
|
||||
private var session: ApplicationsState.Session? = null
|
||||
|
||||
// Flag used to avoid infinite loop due if user switch it on/off too quick.
|
||||
private var switching = false
|
||||
|
||||
override fun onCreate(bundle: Bundle?) {
|
||||
super.onCreate(bundle)
|
||||
|
||||
if (!requireContext().isDataSaverVisible()) {
|
||||
finishFragment()
|
||||
return
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.data_saver)
|
||||
unrestrictedAccess = findPreference(KEY_UNRESTRICTED_ACCESS)!!
|
||||
dataSaverBackend = DataSaverBackend(requireContext())
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
switchBar = (activity as SettingsActivity).switchBar.apply {
|
||||
setTitle(getString(R.string.data_saver_switch_title))
|
||||
show()
|
||||
addOnSwitchChangeListener { _: Switch, isChecked: Boolean ->
|
||||
onSwitchChanged(isChecked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
dataSaverBackend.refreshAllowlist()
|
||||
dataSaverBackend.refreshDenylist()
|
||||
dataSaverBackend.addListener(dataSaverBackendListener)
|
||||
dataUsageBridge?.resume(/* forceLoadAllApps= */ true)
|
||||
?: viewLifecycleOwner.lifecycleScope.launch {
|
||||
val applicationsState = ApplicationsState.getInstance(
|
||||
requireContext().applicationContext as Application
|
||||
)
|
||||
dataUsageBridge = AppStateDataUsageBridge(
|
||||
applicationsState, dataUsageBridgeCallbacks, dataSaverBackend
|
||||
)
|
||||
session =
|
||||
applicationsState.newSession(applicationsStateCallbacks, settingsLifecycle)
|
||||
dataUsageBridge?.resume(/* forceLoadAllApps= */ true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
dataSaverBackend.remListener(dataSaverBackendListener)
|
||||
dataUsageBridge?.pause()
|
||||
}
|
||||
|
||||
private fun onSwitchChanged(isChecked: Boolean) {
|
||||
synchronized(this) {
|
||||
if (!switching) {
|
||||
switching = true
|
||||
dataSaverBackend.isDataSaverEnabled = isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMetricsCategory() = SettingsEnums.DATA_SAVER_SUMMARY
|
||||
|
||||
override fun getHelpResource() = R.string.help_url_data_saver
|
||||
|
||||
private val dataSaverBackendListener = object : DataSaverBackend.Listener {
|
||||
override fun onDataSaverChanged(isDataSaving: Boolean) {
|
||||
synchronized(this) {
|
||||
switchBar.isChecked = isDataSaving
|
||||
switching = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAllowlistStatusChanged(uid: Int, isAllowlisted: Boolean) {}
|
||||
|
||||
override fun onDenylistStatusChanged(uid: Int, isDenylisted: Boolean) {}
|
||||
}
|
||||
|
||||
private val dataUsageBridgeCallbacks = AppStateBaseBridge.Callback {
|
||||
updateUnrestrictedAccessSummary()
|
||||
}
|
||||
|
||||
private val applicationsStateCallbacks = object : ApplicationsState.Callbacks {
|
||||
override fun onRunningStateChanged(running: Boolean) {}
|
||||
|
||||
override fun onPackageListChanged() {}
|
||||
|
||||
override fun onRebuildComplete(apps: ArrayList<ApplicationsState.AppEntry>?) {}
|
||||
|
||||
override fun onPackageIconChanged() {}
|
||||
|
||||
override fun onPackageSizeChanged(packageName: String?) {}
|
||||
|
||||
override fun onAllSizesComputed() {
|
||||
updateUnrestrictedAccessSummary()
|
||||
}
|
||||
|
||||
override fun onLauncherInfoChanged() {
|
||||
updateUnrestrictedAccessSummary()
|
||||
}
|
||||
|
||||
override fun onLoadEntriesCompleted() {}
|
||||
}
|
||||
|
||||
private fun updateUnrestrictedAccessSummary() {
|
||||
if (!isAdded || isFinishingOrDestroyed) return
|
||||
val allApps = session?.allApps ?: return
|
||||
val count = allApps.count {
|
||||
ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(it) &&
|
||||
(it.extraInfo as? DataUsageState)?.isDataSaverAllowlisted == true
|
||||
}
|
||||
unrestrictedAccess.summary =
|
||||
resources.formatString(R.string.data_saver_unrestricted_summary, "count" to count)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_UNRESTRICTED_ACCESS = "unrestricted_access"
|
||||
|
||||
private fun Context.isDataSaverVisible(): Boolean =
|
||||
resources.getBoolean(R.bool.config_show_data_saver)
|
||||
|
||||
@JvmField
|
||||
val SEARCH_INDEX_DATA_PROVIDER = object : BaseSearchIndexProvider(R.xml.data_saver) {
|
||||
override fun isPageSearchEnabled(context: Context): Boolean =
|
||||
context.isDataSaverVisible() &&
|
||||
DataUsageUtils.hasMobileData(context) &&
|
||||
(DataUsageUtils.getDefaultSubscriptionId(context) !=
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID)
|
||||
}
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import android.os.PowerManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -63,7 +64,7 @@ public class AmbientDisplayAlwaysOnPreferenceController extends TogglePreference
|
||||
|
||||
@Override
|
||||
public boolean isPublicSlice() {
|
||||
return true;
|
||||
return TextUtils.equals(getPreferenceKey(), "ambient_display_always_on");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -30,6 +30,7 @@ import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
|
||||
@@ -37,11 +38,13 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
|
||||
private static final String TAG = "TopLvBatteryPrefControl";
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean mIsBatteryPresent = true;
|
||||
@VisibleForTesting
|
||||
Preference mPreference;
|
||||
@VisibleForTesting
|
||||
protected boolean mIsBatteryPresent = true;
|
||||
|
||||
private final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
|
||||
|
||||
private BatteryInfo mBatteryInfo;
|
||||
private BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
|
||||
private String mBatteryStatusLabel;
|
||||
@@ -55,8 +58,11 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
mIsBatteryPresent = false;
|
||||
}
|
||||
BatteryInfo.getBatteryInfo(mContext, info -> {
|
||||
Log.d(TAG, "getBatteryInfo: " + info);
|
||||
mBatteryInfo = info;
|
||||
updateState(mPreference);
|
||||
// Update the preference summary text to the latest state.
|
||||
setSummaryAsync(info);
|
||||
}, true /* shortString */);
|
||||
});
|
||||
|
||||
@@ -104,18 +110,19 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
if (info == null || context == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.d(TAG, "getDashboardLabel: batteryStatusUpdate=" + batteryStatusUpdate);
|
||||
Log.d(TAG, "getDashboardLabel: " + mBatteryStatusLabel + " batteryStatusUpdate="
|
||||
+ batteryStatusUpdate);
|
||||
|
||||
if (batteryStatusUpdate) {
|
||||
setSummaryAsync(info);
|
||||
}
|
||||
|
||||
return (mBatteryStatusLabel == null) ? generateLabel(info) : mBatteryStatusLabel;
|
||||
return mBatteryStatusLabel == null ? generateLabel(info) : mBatteryStatusLabel;
|
||||
}
|
||||
|
||||
private void setSummaryAsync(BatteryInfo info) {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
// Return false if built-in status should be used, will use updateBatteryStatus()
|
||||
// method to inject the customized battery status label.
|
||||
final boolean triggerBatteryStatusUpdate =
|
||||
mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info);
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
@@ -123,12 +130,15 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
mBatteryStatusLabel = null; // will generateLabel()
|
||||
}
|
||||
mPreference.setSummary(
|
||||
(mBatteryStatusLabel == null) ? generateLabel(info) : mBatteryStatusLabel);
|
||||
mBatteryStatusLabel == null ? generateLabel(info) : mBatteryStatusLabel);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private CharSequence generateLabel(BatteryInfo info) {
|
||||
if (Utils.containsIncompatibleChargers(mContext, TAG)) {
|
||||
return mContext.getString(R.string.battery_info_status_not_charging);
|
||||
}
|
||||
if (!info.discharging && info.chargeLabel != null) {
|
||||
return info.chargeLabel;
|
||||
} else if (info.remainingLabel == null) {
|
||||
@@ -146,13 +156,13 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
@Override
|
||||
public void updateBatteryStatus(String label, BatteryInfo info) {
|
||||
mBatteryStatusLabel = label; // Null if adaptive charging is not active
|
||||
|
||||
if (mPreference != null) {
|
||||
// Do not triggerBatteryStatusUpdate(), otherwise there will be an infinite loop
|
||||
final CharSequence summary = getSummary(false /* batteryStatusUpdate */);
|
||||
if (summary != null) {
|
||||
mPreference.setSummary(summary);
|
||||
}
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
// Do not triggerBatteryStatusUpdate() here to cause infinite loop
|
||||
final CharSequence summary = getSummary(false /* batteryStatusUpdate */);
|
||||
if (summary != null) {
|
||||
mPreference.setSummary(summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,4 +180,4 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
|
||||
String pkgName = lastPkgIndex > 0 ? classPath.substring(0, lastPkgIndex) : "";
|
||||
return new ComponentName(pkgName, split[classNameIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,16 +25,19 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.XmlTestUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowKeyCharacterMap;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link SystemControlsFragment}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowKeyCharacterMap.class})
|
||||
public class SystemControlsFragmentTest {
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
@@ -23,12 +23,15 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
|
||||
|
||||
@@ -45,10 +48,15 @@ public class ClonedAppsPreferenceControllerTest {
|
||||
private ClonedAppsPreferenceController mController;
|
||||
private static final String KEY = "key";
|
||||
private Context mContext;
|
||||
private Resources mResources;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
|
||||
mResources = spy(mContext.getResources());
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
|
||||
mController = new ClonedAppsPreferenceController(mContext, KEY);
|
||||
}
|
||||
|
||||
@@ -56,6 +64,7 @@ public class ClonedAppsPreferenceControllerTest {
|
||||
public void getAvailabilityStatus_featureNotEnabled_shouldNotReturnAvailable() {
|
||||
DeviceConfig.setProperty(NAMESPACE_APP_CLONING, Utils.PROPERTY_CLONED_APPS_ENABLED,
|
||||
"false", true /* makeDefault */);
|
||||
when(mResources.getBoolean(R.bool.config_cloned_apps_page_enabled)).thenReturn(false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
|
||||
}
|
||||
@@ -64,7 +73,26 @@ public class ClonedAppsPreferenceControllerTest {
|
||||
public void getAvailabilityStatus_featureEnabled_shouldReturnAvailable() {
|
||||
DeviceConfig.setProperty(NAMESPACE_APP_CLONING, Utils.PROPERTY_CLONED_APPS_ENABLED,
|
||||
"true", true /* makeDefault */);
|
||||
when(mResources.getBoolean(R.bool.config_cloned_apps_page_enabled)).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_deviceConfigFalseAndConfigEnabled_shouldNotReturnAvailable() {
|
||||
DeviceConfig.setProperty(NAMESPACE_APP_CLONING, Utils.PROPERTY_CLONED_APPS_ENABLED,
|
||||
"false", true /* makeDefault */);
|
||||
when(mResources.getBoolean(R.bool.config_cloned_apps_page_enabled)).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_deviceConfigTrueAndConfigDisabled_shouldNotReturnAvailable() {
|
||||
DeviceConfig.setProperty(NAMESPACE_APP_CLONING, Utils.PROPERTY_CLONED_APPS_ENABLED,
|
||||
"true", true /* makeDefault */);
|
||||
when(mResources.getBoolean(R.bool.config_cloned_apps_page_enabled)).thenReturn(false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,9 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.hardware.usb.UsbPort;
|
||||
import android.hardware.usb.UsbPortStatus;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@@ -38,21 +41,33 @@ import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TopLevelBatteryPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private TopLevelBatteryPreferenceController mController;
|
||||
private BatterySettingsFeatureProvider mBatterySettingsFeatureProvider;
|
||||
|
||||
@Mock
|
||||
private UsbPort mUsbPort;
|
||||
@Mock
|
||||
private UsbManager mUsbManager;
|
||||
@Mock
|
||||
private UsbPortStatus mUsbPortStatus;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mController = new TopLevelBatteryPreferenceController(mContext, "test_key");
|
||||
when(mContext.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,27 +103,61 @@ public class TopLevelBatteryPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_returnsCorrectLabel() {
|
||||
public void getDashboardLabel_returnsBatterPercentString() {
|
||||
mController.mPreference = new Preference(mContext);
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.batteryPercentString = "3%";
|
||||
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true))
|
||||
.isEqualTo(info.batteryPercentString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_returnsRemainingLabel() {
|
||||
mController.mPreference = new Preference(mContext);
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.batteryPercentString = "3%";
|
||||
info.remainingLabel = "Phone will shut down soon";
|
||||
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true))
|
||||
.isEqualTo("3% - Phone will shut down soon");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_returnsChargeLabel() {
|
||||
mController.mPreference = new Preference(mContext);
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
info.discharging = false;
|
||||
info.chargeLabel = "5% - charging";
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true)).isEqualTo("5% - charging");
|
||||
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true))
|
||||
.isEqualTo(info.chargeLabel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDashboardLabel_incompatibleCharger_returnsCorrectLabel() {
|
||||
setupIncompatibleEvent();
|
||||
mController.mPreference = new Preference(mContext);
|
||||
BatteryInfo info = new BatteryInfo();
|
||||
|
||||
assertThat(mController.getDashboardLabel(mContext, info, true))
|
||||
.isEqualTo(mContext.getString(R.string.battery_info_status_not_charging));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_batteryNotPresent_shouldShowWarningMessage() {
|
||||
mController.mIsBatteryPresent = false;
|
||||
|
||||
assertThat(mController.getSummary())
|
||||
.isEqualTo(mContext.getString(R.string.battery_missing_message));
|
||||
}
|
||||
|
||||
private void setupIncompatibleEvent() {
|
||||
final List<UsbPort> usbPorts = new ArrayList<>();
|
||||
usbPorts.add(mUsbPort);
|
||||
when(mUsbManager.getPorts()).thenReturn(usbPorts);
|
||||
when(mUsbPort.getStatus()).thenReturn(mUsbPortStatus);
|
||||
when(mUsbPort.supportsComplianceWarnings()).thenReturn(true);
|
||||
when(mUsbPortStatus.isConnected()).thenReturn(true);
|
||||
when(mUsbPortStatus.getComplianceWarnings()).thenReturn(new int[]{1});
|
||||
}
|
||||
}
|
||||
|
@@ -169,6 +169,7 @@ public class PrivateDnsPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailibilityStatus_availableByDefault() {
|
||||
doReturn(true).when(mUserManager).isAdminUser();
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user