Merge "Add BatteryFix Slice"

This commit is contained in:
Raff Tsai
2018-11-21 05:57:32 +00:00
committed by Android (Google) Code Review
9 changed files with 468 additions and 35 deletions

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -0,0 +1,224 @@
/*
* 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() {
}
}
}

View File

@@ -20,10 +20,13 @@ import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
import androidx.annotation.VisibleForTesting;
import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.DeviceInfoSlice;
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
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.wifi.WifiSlice;
@@ -34,13 +37,11 @@ import java.util.WeakHashMap;
/**
* Manages custom {@link androidx.slice.Slice Slices}, which are all Slices not backed by
* preferences.
* <p>
* By default, all Slices in Settings should be built by a
* </p>
*/
public class CustomSliceManager {
protected final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
@VisibleForTesting
final Map<Uri, Class<? extends CustomSliceable>> mUriMap;
private final Context mContext;
private final Map<Uri, CustomSliceable> mSliceableCache;
@@ -107,5 +108,6 @@ public class CustomSliceManager {
mUriMap.put(BatterySlice.BATTERY_CARD_URI, BatterySlice.class);
mUriMap.put(ConnectedDeviceSlice.CONNECTED_DEVICE_URI, ConnectedDeviceSlice.class);
mUriMap.put(LowStorageSlice.LOW_STORAGE_URI, LowStorageSlice.class);
mUriMap.put(BatteryFixSlice.BATTERY_FIX_URI, BatteryFixSlice.class);
}
}