1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.fuelgauge.batteryusage;
18 
19 import android.content.Context;
20 import android.text.SpannableString;
21 import android.text.Spanned;
22 import android.text.TextUtils;
23 import android.text.style.AbsoluteSizeSpan;
24 
25 import androidx.preference.PreferenceCategory;
26 import androidx.preference.PreferenceScreen;
27 
28 import com.android.internal.annotations.VisibleForTesting;
29 import com.android.settings.R;
30 import com.android.settings.Utils;
31 import com.android.settings.core.BasePreferenceController;
32 import com.android.settings.fuelgauge.BatteryUtils;
33 
34 import java.util.Locale;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37 
38 /** Controller for screen on time in battery usage page. */
39 public class ScreenOnTimeController extends BasePreferenceController {
40     private static final String TAG = "ScreenOnTimeController";
41     private static final String ROOT_PREFERENCE_KEY = "screen_on_time_category";
42     private static final String SCREEN_ON_TIME_TEXT_PREFERENCE_KEY = "screen_on_time_text";
43     private static final Pattern NUMBER_PATTERN = Pattern.compile("[\\d]*[\\.,]?[\\d]+");
44     private static final Locale IW_LOCALE = new Locale("iw");
45 
46     @VisibleForTesting Context mPrefContext;
47     @VisibleForTesting PreferenceCategory mRootPreference;
48     @VisibleForTesting TextViewPreference mScreenOnTimeTextPreference;
49     @VisibleForTesting String mScreenTimeCategoryLastFullChargeText;
50 
ScreenOnTimeController(Context context)51     public ScreenOnTimeController(Context context) {
52         super(context, ROOT_PREFERENCE_KEY);
53     }
54 
55     @Override
getAvailabilityStatus()56     public int getAvailabilityStatus() {
57         return AVAILABLE;
58     }
59 
60     @Override
displayPreference(PreferenceScreen screen)61     public void displayPreference(PreferenceScreen screen) {
62         super.displayPreference(screen);
63         mPrefContext = screen.getContext();
64         mRootPreference = screen.findPreference(ROOT_PREFERENCE_KEY);
65         mScreenOnTimeTextPreference = screen.findPreference(SCREEN_ON_TIME_TEXT_PREFERENCE_KEY);
66         mScreenTimeCategoryLastFullChargeText =
67                 mPrefContext.getString(R.string.screen_time_category_last_full_charge);
68     }
69 
handleScreenOnTimeUpdated( Long screenOnTime, String slotTimestamp, String accessibilitySlotTimestamp)70     void handleScreenOnTimeUpdated(
71             Long screenOnTime, String slotTimestamp, String accessibilitySlotTimestamp) {
72         if (screenOnTime == null) {
73             mRootPreference.setVisible(false);
74             mScreenOnTimeTextPreference.setVisible(false);
75             return;
76         }
77         showCategoryTitle(slotTimestamp, accessibilitySlotTimestamp);
78         showScreenOnTimeText(screenOnTime);
79     }
80 
81     @VisibleForTesting
showCategoryTitle(String slotTimestamp, String accessibilitySlotTimestamp)82     void showCategoryTitle(String slotTimestamp, String accessibilitySlotTimestamp) {
83         final String displayTitle =
84                 slotTimestamp == null
85                         ? mScreenTimeCategoryLastFullChargeText
86                         : mPrefContext.getString(
87                                 R.string.screen_time_category_for_slot, slotTimestamp);
88         final String accessibilityTitle =
89                 accessibilitySlotTimestamp == null
90                         ? mScreenTimeCategoryLastFullChargeText
91                         : mPrefContext.getString(
92                                 R.string.screen_time_category_for_slot, accessibilitySlotTimestamp);
93         mRootPreference.setTitle(Utils.createAccessibleSequence(displayTitle, accessibilityTitle));
94         mRootPreference.setVisible(true);
95     }
96 
97     @VisibleForTesting
showScreenOnTimeText(Long screenOnTime)98     void showScreenOnTimeText(Long screenOnTime) {
99         final CharSequence timeSequence =
100                 BatteryUtils.formatElapsedTimeWithoutComma(
101                         mPrefContext,
102                         (double) screenOnTime,
103                         /* withSeconds= */ false,
104                         /* collapseTimeUnit= */ false);
105         mScreenOnTimeTextPreference.setText(
106                 enlargeFontOfNumberIfNeeded(mPrefContext, timeSequence));
107         mScreenOnTimeTextPreference.setVisible(true);
108     }
109 
110     @VisibleForTesting
enlargeFontOfNumberIfNeeded(Context context, CharSequence text)111     static CharSequence enlargeFontOfNumberIfNeeded(Context context, CharSequence text) {
112         if (TextUtils.isEmpty(text)) {
113             return "";
114         }
115 
116         final Locale locale = context.getResources().getConfiguration().getLocales().get(0);
117         if (locale != null && IW_LOCALE.getLanguage().equals(locale.getLanguage())) {
118             return text;
119         }
120 
121         final SpannableString spannableText = new SpannableString(text);
122         final Matcher matcher = NUMBER_PATTERN.matcher(text);
123         while (matcher.find()) {
124             spannableText.setSpan(
125                     new AbsoluteSizeSpan(36, true /* dip */),
126                     matcher.start(),
127                     matcher.end(),
128                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
129         }
130         return spannableText;
131     }
132 }
133