PowerUI.java revision ed452c5f84c2c12059a247523d768f1eb280934b
1/* 2 * Copyright (C) 2008 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 17package com.android.systemui.power; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.os.BatteryManager; 24import android.os.Handler; 25import android.os.PowerManager; 26import android.os.SystemClock; 27import android.provider.Settings; 28import android.util.Slog; 29 30import com.android.systemui.SystemUI; 31 32import java.io.FileDescriptor; 33import java.io.PrintWriter; 34import java.util.Arrays; 35 36public class PowerUI extends SystemUI { 37 static final String TAG = "PowerUI"; 38 39 static final boolean DEBUG = false; 40 41 private WarningsUI mWarnings; 42 43 private final Handler mHandler = new Handler(); 44 45 private int mBatteryLevel = 100; 46 private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; 47 private int mPlugType = 0; 48 private int mInvalidCharger = 0; 49 50 private int mLowBatteryAlertCloseLevel; 51 private final int[] mLowBatteryReminderLevels = new int[2]; 52 53 private long mScreenOffTime = -1; 54 55 public void start() { 56 57 mLowBatteryAlertCloseLevel = mContext.getResources().getInteger( 58 com.android.internal.R.integer.config_lowBatteryCloseWarningLevel); 59 mLowBatteryReminderLevels[0] = mContext.getResources().getInteger( 60 com.android.internal.R.integer.config_lowBatteryWarningLevel); 61 mLowBatteryReminderLevels[1] = mContext.getResources().getInteger( 62 com.android.internal.R.integer.config_criticalBatteryWarningLevel); 63 64 final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 65 mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); 66 mWarnings = new PowerDialogWarnings(mContext); 67 68 // Register for Intent broadcasts for... 69 IntentFilter filter = new IntentFilter(); 70 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 71 filter.addAction(Intent.ACTION_SCREEN_OFF); 72 filter.addAction(Intent.ACTION_SCREEN_ON); 73 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); 74 } 75 76 /** 77 * Buckets the battery level. 78 * 79 * The code in this function is a little weird because I couldn't comprehend 80 * the bucket going up when the battery level was going down. --joeo 81 * 82 * 1 means that the battery is "ok" 83 * 0 means that the battery is between "ok" and what we should warn about. 84 * less than 0 means that the battery is low 85 */ 86 private int findBatteryLevelBucket(int level) { 87 if (level >= mLowBatteryAlertCloseLevel) { 88 return 1; 89 } 90 if (level >= mLowBatteryReminderLevels[0]) { 91 return 0; 92 } 93 final int N = mLowBatteryReminderLevels.length; 94 for (int i=N-1; i>=0; i--) { 95 if (level <= mLowBatteryReminderLevels[i]) { 96 return -1-i; 97 } 98 } 99 throw new RuntimeException("not possible!"); 100 } 101 102 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 103 @Override 104 public void onReceive(Context context, Intent intent) { 105 String action = intent.getAction(); 106 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 107 final int oldBatteryLevel = mBatteryLevel; 108 mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100); 109 final int oldBatteryStatus = mBatteryStatus; 110 mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 111 BatteryManager.BATTERY_STATUS_UNKNOWN); 112 final int oldPlugType = mPlugType; 113 mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1); 114 final int oldInvalidCharger = mInvalidCharger; 115 mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0); 116 117 final boolean plugged = mPlugType != 0; 118 final boolean oldPlugged = oldPlugType != 0; 119 120 int oldBucket = findBatteryLevelBucket(oldBatteryLevel); 121 int bucket = findBatteryLevelBucket(mBatteryLevel); 122 123 if (DEBUG) { 124 Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel 125 + " .. " + mLowBatteryReminderLevels[0] 126 + " .. " + mLowBatteryReminderLevels[1]); 127 Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel); 128 Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus); 129 Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType); 130 Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger); 131 Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket); 132 Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged); 133 } 134 135 mWarnings.update(mBatteryLevel, bucket, mScreenOffTime); 136 if (oldInvalidCharger == 0 && mInvalidCharger != 0) { 137 Slog.d(TAG, "showing invalid charger warning"); 138 mWarnings.showInvalidChargerWarning(); 139 return; 140 } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) { 141 mWarnings.dismissInvalidChargerWarning(); 142 } else if (mWarnings.isInvalidChargerWarningShowing()) { 143 // if invalid charger is showing, don't show low battery 144 return; 145 } 146 147 if (!plugged 148 && (bucket < oldBucket || oldPlugged) 149 && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN 150 && bucket < 0) { 151 // only play SFX when the dialog comes up or the bucket changes 152 final boolean playSound = bucket != oldBucket || oldPlugged; 153 mWarnings.showLowBatteryWarning(playSound); 154 } else if (plugged || (bucket > oldBucket && bucket > 0)) { 155 mWarnings.dismissLowBatteryWarning(); 156 } else { 157 mWarnings.updateLowBatteryWarning(); 158 } 159 } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { 160 mScreenOffTime = SystemClock.elapsedRealtime(); 161 } else if (Intent.ACTION_SCREEN_ON.equals(action)) { 162 mScreenOffTime = -1; 163 } else { 164 Slog.w(TAG, "unknown intent: " + intent); 165 } 166 } 167 }; 168 169 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 170 pw.print("mLowBatteryAlertCloseLevel="); 171 pw.println(mLowBatteryAlertCloseLevel); 172 pw.print("mLowBatteryReminderLevels="); 173 pw.println(Arrays.toString(mLowBatteryReminderLevels)); 174 pw.print("mBatteryLevel="); 175 pw.println(Integer.toString(mBatteryLevel)); 176 pw.print("mBatteryStatus="); 177 pw.println(Integer.toString(mBatteryStatus)); 178 pw.print("mPlugType="); 179 pw.println(Integer.toString(mPlugType)); 180 pw.print("mInvalidCharger="); 181 pw.println(Integer.toString(mInvalidCharger)); 182 pw.print("mScreenOffTime="); 183 pw.print(mScreenOffTime); 184 if (mScreenOffTime >= 0) { 185 pw.print(" ("); 186 pw.print(SystemClock.elapsedRealtime() - mScreenOffTime); 187 pw.print(" ago)"); 188 } 189 pw.println(); 190 pw.print("soundTimeout="); 191 pw.println(Settings.Global.getInt(mContext.getContentResolver(), 192 Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0)); 193 pw.print("bucket: "); 194 pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel))); 195 mWarnings.dump(pw); 196 } 197 198 public interface WarningsUI { 199 void update(int batteryLevel, int bucket, long screenOffTime); 200 void dismissLowBatteryWarning(); 201 void showLowBatteryWarning(boolean playSound); 202 void dismissInvalidChargerWarning(); 203 void showInvalidChargerWarning(); 204 void updateLowBatteryWarning(); 205 boolean isInvalidChargerWarningShowing(); 206 void dump(PrintWriter pw); 207 } 208} 209 210