1 /* 2 * Copyright (C) 2018 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.batterytip; 18 19 import android.app.Dialog; 20 import android.app.settings.SettingsEnums; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.os.BatteryManager; 26 import android.os.Bundle; 27 import android.view.LayoutInflater; 28 29 import androidx.annotation.VisibleForTesting; 30 import androidx.appcompat.app.AlertDialog; 31 import androidx.recyclerview.widget.LinearLayoutManager; 32 import androidx.recyclerview.widget.RecyclerView; 33 34 import com.android.settings.R; 35 import com.android.settings.SettingsActivity; 36 import com.android.settings.Utils; 37 import com.android.settings.core.InstrumentedPreferenceFragment; 38 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 39 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController.BatteryTipListener; 40 import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction; 41 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; 42 import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; 43 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; 44 import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; 45 46 import java.text.NumberFormat; 47 import java.util.List; 48 49 /** 50 * Dialog Fragment to show action dialog for each anomaly 51 */ 52 public class BatteryTipDialogFragment extends InstrumentedDialogFragment implements 53 DialogInterface.OnClickListener { 54 55 private static final String ARG_BATTERY_TIP = "battery_tip"; 56 private static final String ARG_METRICS_KEY = "metrics_key"; 57 private static final double CHARGE_LIMIT_LEVEL = 0.8f; 58 59 @VisibleForTesting 60 BatteryTip mBatteryTip; 61 @VisibleForTesting 62 int mMetricsKey; 63 newInstance(BatteryTip batteryTip, int metricsKey)64 public static BatteryTipDialogFragment newInstance(BatteryTip batteryTip, int metricsKey) { 65 BatteryTipDialogFragment dialogFragment = new BatteryTipDialogFragment(); 66 67 Bundle args = new Bundle(1); 68 args.putParcelable(ARG_BATTERY_TIP, batteryTip); 69 args.putInt(ARG_METRICS_KEY, metricsKey); 70 dialogFragment.setArguments(args); 71 72 return dialogFragment; 73 } 74 75 @Override onCreateDialog(Bundle savedInstanceState)76 public Dialog onCreateDialog(Bundle savedInstanceState) { 77 final Bundle bundle = getArguments(); 78 final Context context = getContext(); 79 80 mBatteryTip = bundle.getParcelable(ARG_BATTERY_TIP); 81 mMetricsKey = bundle.getInt(ARG_METRICS_KEY); 82 83 switch (mBatteryTip.getType()) { 84 case BatteryTip.TipType.SUMMARY: 85 return new AlertDialog.Builder(context) 86 .setMessage(R.string.battery_tip_dialog_summary_message) 87 .setPositiveButton(android.R.string.ok, null) 88 .create(); 89 case BatteryTip.TipType.HIGH_DEVICE_USAGE: 90 final HighUsageTip highUsageTip = (HighUsageTip) mBatteryTip; 91 final RecyclerView view = (RecyclerView) LayoutInflater.from(context).inflate( 92 R.layout.recycler_view, 93 null); 94 view.setLayoutManager(new LinearLayoutManager(context)); 95 view.setAdapter(new HighUsageAdapter(context, 96 highUsageTip.getHighUsageAppList())); 97 98 return new AlertDialog.Builder(context) 99 .setMessage(getString(R.string.battery_tip_dialog_message, 100 highUsageTip.getHighUsageAppList().size())) 101 .setView(view) 102 .setPositiveButton(android.R.string.ok, null) 103 .create(); 104 case BatteryTip.TipType.APP_RESTRICTION: 105 final RestrictAppTip restrictAppTip = (RestrictAppTip) mBatteryTip; 106 final List<AppInfo> restrictedAppList = restrictAppTip.getRestrictAppList(); 107 final int num = restrictedAppList.size(); 108 final CharSequence appLabel = Utils.getApplicationLabel(context, 109 restrictedAppList.get(0).packageName); 110 111 final AlertDialog.Builder builder = new AlertDialog.Builder(context) 112 .setTitle(context.getResources().getQuantityString( 113 R.plurals.battery_tip_restrict_app_dialog_title, num, num)) 114 .setPositiveButton(R.string.battery_tip_restrict_app_dialog_ok, this) 115 .setNegativeButton(android.R.string.cancel, null); 116 if (num == 1) { 117 builder.setMessage( 118 getString(R.string.battery_tip_restrict_app_dialog_message, appLabel)); 119 } else if (num <= 5) { 120 builder.setMessage( 121 getString( 122 R.string.battery_tip_restrict_apps_less_than_5_dialog_message)); 123 final RecyclerView restrictionView = (RecyclerView) LayoutInflater.from( 124 context).inflate(R.layout.recycler_view, null); 125 restrictionView.setLayoutManager(new LinearLayoutManager(context)); 126 restrictionView.setAdapter(new HighUsageAdapter(context, restrictedAppList)); 127 builder.setView(restrictionView); 128 } else { 129 builder.setMessage(context.getString( 130 R.string.battery_tip_restrict_apps_more_than_5_dialog_message, 131 restrictAppTip.getRestrictAppsString(context))); 132 } 133 134 return builder.create(); 135 case BatteryTip.TipType.REMOVE_APP_RESTRICTION: 136 final UnrestrictAppTip unrestrictAppTip = (UnrestrictAppTip) mBatteryTip; 137 final CharSequence name = Utils.getApplicationLabel(context, 138 unrestrictAppTip.getPackageName()); 139 140 return new AlertDialog.Builder(context) 141 .setTitle(getString(R.string.battery_tip_unrestrict_app_dialog_title)) 142 .setMessage(R.string.battery_tip_unrestrict_app_dialog_message) 143 .setPositiveButton(R.string.battery_tip_unrestrict_app_dialog_ok, this) 144 .setNegativeButton(R.string.battery_tip_unrestrict_app_dialog_cancel, null) 145 .create(); 146 case BatteryTip.TipType.BATTERY_DEFENDER: 147 mMetricsFeatureProvider.action(context, 148 SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, mMetricsKey); 149 final String percentage = 150 NumberFormat.getPercentInstance().format(CHARGE_LIMIT_LEVEL); 151 final String message = context.getString( 152 R.string.battery_tip_limited_temporarily_dialog_msg, percentage); 153 final boolean isPluggedIn = isPluggedIn(); 154 final AlertDialog.Builder dialogBuilder = 155 new AlertDialog.Builder(context) 156 .setTitle(R.string.battery_tip_limited_temporarily_title) 157 .setMessage(message); 158 if (isPluggedIn) { 159 dialogBuilder 160 .setPositiveButton( 161 R.string.battery_tip_limited_temporarily_dialog_resume_charge, 162 this) 163 .setNegativeButton(R.string.okay, null); 164 } else { 165 dialogBuilder.setPositiveButton(R.string.okay, null); 166 } 167 return dialogBuilder.create(); 168 default: 169 throw new IllegalArgumentException("unknown type " + mBatteryTip.getType()); 170 } 171 } 172 173 @Override getMetricsCategory()174 public int getMetricsCategory() { 175 return SettingsEnums.FUELGAUGE_BATTERY_TIP_DIALOG; 176 } 177 178 @Override onClick(DialogInterface dialog, int which)179 public void onClick(DialogInterface dialog, int which) { 180 final BatteryTipListener lsn = (BatteryTipListener) getTargetFragment(); 181 if (lsn == null) { 182 return; 183 } 184 final BatteryTipAction action = BatteryTipUtils.getActionForBatteryTip(mBatteryTip, 185 (SettingsActivity) getActivity(), 186 (InstrumentedPreferenceFragment) getTargetFragment()); 187 if (action != null) { 188 action.handlePositiveAction(mMetricsKey); 189 } 190 lsn.onBatteryTipHandled(mBatteryTip); 191 } 192 isPluggedIn()193 private boolean isPluggedIn() { 194 final Intent batteryIntent = getContext().registerReceiver(null /* receiver */, 195 new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 196 return batteryIntent != null && batteryIntent.getIntExtra( 197 BatteryManager.EXTRA_PLUGGED, 0) != 0; 198 } 199 200 } 201