Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbbbd7a8 authored by Raff Tsai's avatar Raff Tsai Committed by Android (Google) Code Review
Browse files

Merge "Add BatteryFix Slice"

parents e471b656 b92e9d42
Loading
Loading
Loading
Loading
+65 −29
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>
<issues format="4">

    <issue
        id="LintError"
        severity="Error"
        message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
        category="Lint"
        priority="10"
        summary="Lint Failure"
        explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
        <location
            file="."/>
    </issue>

    <issue
        id="HardCodedColor"
        severity="Error"
@@ -2553,7 +2541,7 @@
        errorLine2="                                                                                                                                                                       ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values-en-rXC/strings.xml"
            line="2530"
            line="2533"
            column="168"/>
    </issue>

@@ -2569,7 +2557,7 @@
        errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values-en-rAU/strings.xml"
            line="2531"
            line="2534"
            column="64"/>
    </issue>

@@ -2585,7 +2573,7 @@
        errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values-en-rCA/strings.xml"
            line="2531"
            line="2534"
            column="64"/>
    </issue>

@@ -2601,7 +2589,7 @@
        errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values-en-rGB/strings.xml"
            line="2531"
            line="2534"
            column="64"/>
    </issue>

@@ -2617,7 +2605,7 @@
        errorLine2="                                                               ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values-en-rIN/strings.xml"
            line="2531"
            line="2534"
            column="64"/>
    </issue>

@@ -2633,7 +2621,7 @@
        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
        <location
            file="res/values/strings.xml"
            line="5886"
            line="5902"
            column="36"/>
    </issue>

@@ -2665,7 +2653,7 @@
        errorLine2="                                           ^">
        <location
            file="res/values/styles.xml"
            line="443"
            line="448"
            column="44"/>
    </issue>

@@ -2681,7 +2669,7 @@
        errorLine2="                                           ^">
        <location
            file="res/values/styles.xml"
            line="449"
            line="454"
            column="44"/>
    </issue>

@@ -2697,7 +2685,7 @@
        errorLine2="                                           ^">
        <location
            file="res/values/styles.xml"
            line="450"
            line="455"
            column="44"/>
    </issue>

@@ -2761,7 +2749,7 @@
        errorLine2="                                              ^">
        <location
            file="res/values/themes.xml"
            line="91"
            line="90"
            column="47"/>
    </issue>

@@ -2777,7 +2765,7 @@
        errorLine2="                                              ^">
        <location
            file="res/values/themes.xml"
            line="91"
            line="90"
            column="47"/>
    </issue>

@@ -2793,7 +2781,7 @@
        errorLine2="                                       ^">
        <location
            file="res/values/themes.xml"
            line="97"
            line="96"
            column="40"/>
    </issue>

@@ -2809,7 +2797,7 @@
        errorLine2="                                       ^">
        <location
            file="res/values/themes.xml"
            line="97"
            line="96"
            column="40"/>
    </issue>

@@ -2825,7 +2813,7 @@
        errorLine2="                                            ^">
        <location
            file="res/values/themes.xml"
            line="160"
            line="159"
            column="45"/>
    </issue>

@@ -2841,7 +2829,7 @@
        errorLine2="                                                ^">
        <location
            file="res/values/themes.xml"
            line="161"
            line="160"
            column="49"/>
    </issue>

@@ -2857,7 +2845,7 @@
        errorLine2="                                            ^">
        <location
            file="res/values/themes.xml"
            line="169"
            line="168"
            column="45"/>
    </issue>

@@ -2873,10 +2861,58 @@
        errorLine2="                                                ^">
        <location
            file="res/values/themes.xml"
            line="170"
            line="169"
            column="49"/>
    </issue>

    <issue
        id="HardCodedColor"
        severity="Error"
        message="Avoid using hardcoded color"
        category="Correctness"
        priority="4"
        summary="Using hardcoded color"
        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
        errorLine1="        &lt;item name=&quot;batteryGoodColor&quot;>@color/battery_good_color_light&lt;/item>"
        errorLine2="                                      ^">
        <location
            file="res/values/themes.xml"
            line="185"
            column="39"/>
    </issue>

    <issue
        id="HardCodedColor"
        severity="Error"
        message="Avoid using hardcoded color"
        category="Correctness"
        priority="4"
        summary="Using hardcoded color"
        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
        errorLine1="        &lt;item name=&quot;batteryMaybeColor&quot;>@color/battery_maybe_color_light&lt;/item>"
        errorLine2="                                       ^">
        <location
            file="res/values/themes.xml"
            line="186"
            column="40"/>
    </issue>

    <issue
        id="HardCodedColor"
        severity="Error"
        message="Avoid using hardcoded color"
        category="Correctness"
        priority="4"
        summary="Using hardcoded color"
        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
        errorLine1="        &lt;item name=&quot;batteryBadColor&quot;>@color/battery_bad_color_light&lt;/item>"
        errorLine2="                                     ^">
        <location
            file="res/values/themes.xml"
            line="187"
            column="38"/>
    </issue>

    <issue
        id="HardCodedColor"
        severity="Error"
+5 −0
Original line number Diff line number Diff line
@@ -180,6 +180,11 @@

        <!-- action bar, needed for search bar icon tinting -->
        <item name="android:actionBarTheme">@*android:style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>

        <!-- For battery status icons in -->
        <item name="batteryGoodColor">@color/battery_good_color_light</item>
        <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
        <item name="batteryBadColor">@color/battery_bad_color_light</item>
    </style>

    <style name="Theme.Settings.Home" parent="Theme.Settings.HomeBase">
+2 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;

import com.android.settings.Utils;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -115,6 +116,6 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver {
                mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER);
            }
        }
        BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext);
    }

}
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.provider.SettingsSlicesContract.KEY_WIFI;
import android.annotation.Nullable;

import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.intelligence.ContextualCardProto.ContextualCard;
@@ -61,11 +62,18 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
                        .setCardName(LowStorageSlice.PATH_LOW_STORAGE)
                        .setCardCategory(ContextualCard.Category.IMPORTANT)
                        .build();
        final ContextualCard batteryFixCard =
                ContextualCard.newBuilder()
                        .setSliceUri(BatteryFixSlice.BATTERY_FIX_URI.toString())
                        .setCardName(BatteryFixSlice.PATH_BATTERY_FIX)
                        .setCardCategory(ContextualCard.Category.IMPORTANT)
                        .build();
        final ContextualCardList cards = ContextualCardList.newBuilder()
                .addCard(wifiCard)
                .addCard(batteryInfoCard)
                .addCard(connectedDeviceCard)
                .addCard(lowStorageCard)
                .addCard(batteryFixCard)
                .build();

        return cards;
+224 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.homepage.contextualcards.slices;

import static android.content.Context.MODE_PRIVATE;

import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;

import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
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;

import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.fuelgauge.batterytip.BatteryTipLoader;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.utils.ThreadUtils;

import java.util.List;

public class BatteryFixSlice implements CustomSliceable {

    /**
     * Unique name of Battery Fix Slice.
     */
    public static final String PATH_BATTERY_FIX = "battery_fix";

    /**
     * Uri for Battery Fix Slice.
     */
    public static final Uri BATTERY_FIX_URI = new Uri.Builder()
            .scheme(ContentResolver.SCHEME_CONTENT)
            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
            .appendPath(PATH_BATTERY_FIX)
            .build();

    @VisibleForTesting
    static final String PREFS = "battery_fix_prefs";
    @VisibleForTesting
    static final String KEY_CURRENT_TIPS_TYPE = "current_tip_type";

    private static final String TAG = "BatteryFixSlice";

    private final Context mContext;

    public BatteryFixSlice(Context context) {
        mContext = context;
    }

    @Override
    public Uri getUri() {
        return BATTERY_FIX_URI;
    }

    /**
     * Return a Slice bound to {@link #BATTERY_FIX_URI}.
     */
    @Override
    public Slice getSlice() {
        IconCompat icon;
        SliceAction primaryAction;
        Slice slice = null;

        // TipType.SUMMARY is battery good
        if (readBatteryTipAvailabilityCache(mContext) == BatteryTip.TipType.SUMMARY) {
            return null;
        }

        final List<BatteryTip> batteryTips = SliceBackgroundWorker.getInstance(mContext,
                this).getResults();

        if (batteryTips != null) {
            for (BatteryTip batteryTip : batteryTips) {
                if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
                    icon = IconCompat.createWithResource(mContext, batteryTip.getIconId());
                    primaryAction = new SliceAction(getPrimaryAction(),
                            icon,
                            batteryTip.getTitle(mContext));
                    slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
                            .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                            .addRow(new RowBuilder()
                                    .setTitle(batteryTip.getTitle(mContext))
                                    .setSubtitle(batteryTip.getSummary(mContext))
                                    .setPrimaryAction(primaryAction)
                                    .addEndItem(icon, ListBuilder.ICON_IMAGE))
                            .build();
                    break;
                }
            }
        } else {
            icon = IconCompat.createWithResource(mContext,
                    R.drawable.ic_battery_status_good_24dp);
            final String title = mContext.getString(R.string.power_usage_summary_title);
            primaryAction = new SliceAction(getPrimaryAction(), icon, title);
            slice = new ListBuilder(mContext, BATTERY_FIX_URI, ListBuilder.INFINITY)
                    .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
                    .addRow(new RowBuilder()
                            .setTitle(title)
                            .setPrimaryAction(primaryAction)
                            .addEndItem(icon, ListBuilder.ICON_IMAGE))
                    .build();
        }
        return slice;
    }

    @Override
    public Intent getIntent() {
        final String screenTitle = mContext.getText(R.string.power_usage_summary_title)
                .toString();
        final Uri contentUri = new Uri.Builder().appendPath(PATH_BATTERY_FIX).build();

        return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
                PowerUsageSummary.class.getName(), PATH_BATTERY_FIX,
                screenTitle,
                MetricsProto.MetricsEvent.SLICE)
                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
                .setData(contentUri);
    }

    @Override
    public void onNotifyChange(Intent intent) {
    }

    @Override
    public Class getBackgroundWorkerClass() {
        return BatteryTipWorker.class;
    }

    private PendingIntent getPrimaryAction() {
        final Intent intent = getIntent();
        return PendingIntent.getActivity(mContext, 0  /* requestCode */, intent, 0  /* flags */);
    }

    // TODO(b/114807643): we should find a better way to get current battery tip type quickly
    // Now we save battery tip type to shared preference when battery level changes
    public static void updateBatteryTipAvailabilityCache(Context context) {
        ThreadUtils.postOnBackgroundThread(() -> {
            refreshBatteryTips(context);
        });
    }

    @VisibleForTesting
    static int readBatteryTipAvailabilityCache(Context context) {
        final SharedPreferences prefs = context.getSharedPreferences(PREFS, MODE_PRIVATE);
        return prefs.getInt(KEY_CURRENT_TIPS_TYPE, BatteryTip.TipType.SUMMARY);
    }

    @WorkerThread
    private static List<BatteryTip> refreshBatteryTips(Context context) {
        final BatteryStatsHelperLoader statsLoader = new BatteryStatsHelperLoader(context);
        final BatteryStatsHelper statsHelper = statsLoader.loadInBackground();
        final BatteryTipLoader loader = new BatteryTipLoader(context, statsHelper);
        final List<BatteryTip> batteryTips = loader.loadInBackground();
        for (BatteryTip batteryTip : batteryTips) {
            if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
                SharedPreferences.Editor editor = context.getSharedPreferences(PREFS,
                        MODE_PRIVATE).edit();
                editor.putInt(KEY_CURRENT_TIPS_TYPE, batteryTip.getType());
                editor.apply();
                break;
            }
        }
        return batteryTips;
    }

    public static class BatteryTipWorker extends SliceBackgroundWorker<BatteryTip> {

        private final Context mContext;

        public BatteryTipWorker(Context context, Uri uri) {
            super(context, uri);
            mContext = context;
        }

        @Override
        protected void onSlicePinned() {
            ThreadUtils.postOnBackgroundThread(() -> {
                final List<BatteryTip> batteryTips = refreshBatteryTips(mContext);
                updateResults(batteryTips);
            });
        }

        @Override
        protected void onSliceUnpinned() {
        }

        @Override
        public void close() {
        }
    }
}
Loading