1/* 2 * Copyright (C) 2014 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.statusbar; 18 19import com.android.internal.app.IBatteryStats; 20import com.android.keyguard.KeyguardUpdateMonitor; 21import com.android.keyguard.KeyguardUpdateMonitorCallback; 22import com.android.systemui.R; 23import com.android.systemui.statusbar.phone.KeyguardIndicationTextView; 24 25import android.content.BroadcastReceiver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.os.BatteryManager; 30import android.os.BatteryStats; 31import android.os.Handler; 32import android.os.Message; 33import android.os.RemoteException; 34import android.os.ServiceManager; 35import android.os.UserHandle; 36import android.text.TextUtils; 37import android.text.format.Formatter; 38import android.util.Log; 39import android.view.View; 40 41/** 42 * Controls the little text indicator on the keyguard. 43 */ 44public class KeyguardIndicationController { 45 46 private static final String TAG = "KeyguardIndicationController"; 47 48 private static final int MSG_HIDE_TRANSIENT = 1; 49 50 private final Context mContext; 51 private final KeyguardIndicationTextView mTextView; 52 private final IBatteryStats mBatteryInfo; 53 54 private String mRestingIndication; 55 private String mTransientIndication; 56 private boolean mVisible; 57 58 private boolean mPowerPluggedIn; 59 private boolean mPowerCharged; 60 61 public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView) { 62 mContext = context; 63 mTextView = textView; 64 65 mBatteryInfo = IBatteryStats.Stub.asInterface( 66 ServiceManager.getService(BatteryStats.SERVICE_NAME)); 67 KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitor); 68 context.registerReceiverAsUser( 69 mReceiver, UserHandle.OWNER, new IntentFilter(Intent.ACTION_TIME_TICK), null, null); 70 } 71 72 public void setVisible(boolean visible) { 73 mVisible = visible; 74 mTextView.setVisibility(visible ? View.VISIBLE : View.GONE); 75 if (visible) { 76 hideTransientIndication(); 77 updateIndication(); 78 } 79 } 80 81 /** 82 * Sets the indication that is shown if nothing else is showing. 83 */ 84 public void setRestingIndication(String restingIndication) { 85 mRestingIndication = restingIndication; 86 updateIndication(); 87 } 88 89 /** 90 * Hides transient indication in {@param delayMs}. 91 */ 92 public void hideTransientIndicationDelayed(long delayMs) { 93 mHandler.sendMessageDelayed( 94 mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs); 95 } 96 97 /** 98 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. 99 */ 100 public void showTransientIndication(int transientIndication) { 101 showTransientIndication(mContext.getResources().getString(transientIndication)); 102 } 103 104 /** 105 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. 106 */ 107 public void showTransientIndication(String transientIndication) { 108 mTransientIndication = transientIndication; 109 mHandler.removeMessages(MSG_HIDE_TRANSIENT); 110 updateIndication(); 111 } 112 113 /** 114 * Hides transient indication. 115 */ 116 public void hideTransientIndication() { 117 if (mTransientIndication != null) { 118 mTransientIndication = null; 119 mHandler.removeMessages(MSG_HIDE_TRANSIENT); 120 updateIndication(); 121 } 122 } 123 124 private void updateIndication() { 125 if (mVisible) { 126 mTextView.switchIndication(computeIndication()); 127 } 128 } 129 130 private String computeIndication() { 131 if (!TextUtils.isEmpty(mTransientIndication)) { 132 return mTransientIndication; 133 } 134 if (mPowerPluggedIn) { 135 return computePowerIndication(); 136 } 137 return mRestingIndication; 138 } 139 140 private String computePowerIndication() { 141 if (mPowerCharged) { 142 return mContext.getResources().getString(R.string.keyguard_charged); 143 } 144 145 // Try fetching charging time from battery stats. 146 try { 147 long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining(); 148 if (chargingTimeRemaining > 0) { 149 String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes( 150 mContext, chargingTimeRemaining); 151 return mContext.getResources().getString( 152 R.string.keyguard_indication_charging_time, chargingTimeFormatted); 153 } 154 } catch (RemoteException e) { 155 Log.e(TAG, "Error calling IBatteryStats: ", e); 156 } 157 158 // Fall back to simple charging label. 159 return mContext.getResources().getString(R.string.keyguard_plugged_in); 160 } 161 162 KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() { 163 @Override 164 public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { 165 boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING 166 || status.status == BatteryManager.BATTERY_STATUS_FULL; 167 mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull; 168 mPowerCharged = status.isCharged(); 169 updateIndication(); 170 } 171 }; 172 173 BroadcastReceiver mReceiver = new BroadcastReceiver() { 174 @Override 175 public void onReceive(Context context, Intent intent) { 176 if (mVisible) { 177 updateIndication(); 178 } 179 } 180 }; 181 182 private final Handler mHandler = new Handler() { 183 @Override 184 public void handleMessage(Message msg) { 185 if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) { 186 mTransientIndication = null; 187 updateIndication(); 188 } 189 } 190 }; 191} 192