content: /*
   * Copyright (C) 2015 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.internal.os;
  
  import android.os.BatteryStats;
  import android.util.Log;
  
  /**
   * Estimates WiFi power usage based on timers in BatteryStats.
   */
  public class WifiPowerEstimator extends PowerCalculator {
      private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
      private static final String TAG = "WifiPowerEstimator";
      private final double mWifiPowerPerPacket;
      private final double mWifiPowerOn;
      private final double mWifiPowerScan;
      private final double mWifiPowerBatchScan;
      private long mTotalAppWifiRunningTimeMs = 0;
  
      public WifiPowerEstimator(PowerProfile profile) {
          mWifiPowerPerPacket = getWifiPowerPerPacket(profile);
          mWifiPowerOn = profile.getAveragePower(PowerProfile.POWER_WIFI_ON);
          mWifiPowerScan = profile.getAveragePower(PowerProfile.POWER_WIFI_SCAN);
          mWifiPowerBatchScan = profile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN);
      }
  
      /**
       * Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
       */
      private static double getWifiPowerPerPacket(PowerProfile profile) {
          final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
          final double WIFI_POWER = profile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
                  / 3600;
          return WIFI_POWER / (((double)WIFI_BPS) / 8 / 2048);
      }
  
      @Override
      public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
                               long rawUptimeUs, int statsType) {
          app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
                  statsType);
          app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
                  statsType);
          app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
                  statsType);
          app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
                  statsType);
  
          final double wifiPacketPower = (app.wifiRxPackets + app.wifiTxPackets)
                  * mWifiPowerPerPacket;
  
          app.wifiRunningTimeMs = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
          mTotalAppWifiRunningTimeMs += app.wifiRunningTimeMs;
          final double wifiLockPower = (app.wifiRunningTimeMs * mWifiPowerOn) / (1000*60*60);
  
          final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
          final double wifiScanPower = (wifiScanTimeMs * mWifiPowerScan) / (1000*60*60);
  
          double wifiBatchScanPower = 0;
          for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
              final long batchScanTimeMs =
                      u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
              final double batchScanPower = (batchScanTimeMs * mWifiPowerBatchScan) / (1000*60*60);
              wifiBatchScanPower += batchScanPower;
          }
  
          app.wifiPowerMah = wifiPacketPower + wifiLockPower + wifiScanPower + wifiBatchScanPower;
          if (DEBUG && app.wifiPowerMah != 0) {
              Log.d(TAG, "UID " + u.getUid() + ": power=" +
                      BatteryStatsHelper.makemAh(app.wifiPowerMah));
          }
      }
  
      @Override
      public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
                                     long rawUptimeUs, int statsType) {
          final long totalRunningTimeMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType)
                  / 1000;
          final double powerDrain = ((totalRunningTimeMs - mTotalAppWifiRunningTimeMs) * mWifiPowerOn)
                  / (1000*60*60);
          app.wifiRunningTimeMs = totalRunningTimeMs;
          app.wifiPowerMah = Math.max(0, powerDrain);
      }
  
      @Override
      public void reset() {
          mTotalAppWifiRunningTimeMs = 0;
      }
  }
  