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 android.os;
  
  import android.annotation.IntDef;
  import android.annotation.NonNull;
  import android.annotation.SystemService;
  import android.content.Context;
  import android.hardware.thermal.V1_0.Constants;
  import android.util.Log;
  
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  
  /**
   * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
   * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
   */
  @SystemService(Context.HARDWARE_PROPERTIES_SERVICE)
  public class HardwarePropertiesManager {
  
      private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
  
      private final IHardwarePropertiesManager mService;
  
      /**
       * @hide
       */
      @Retention(RetentionPolicy.SOURCE)
      @IntDef(prefix = { "DEVICE_TEMPERATURE_" }, value = {
              DEVICE_TEMPERATURE_CPU,
              DEVICE_TEMPERATURE_GPU,
              DEVICE_TEMPERATURE_BATTERY,
              DEVICE_TEMPERATURE_SKIN
      })
      public @interface DeviceTemperatureType {}
  
      /**
       * @hide
       */
      @Retention(RetentionPolicy.SOURCE)
      @IntDef(prefix = { "TEMPERATURE_" }, value = {
              TEMPERATURE_CURRENT,
              TEMPERATURE_THROTTLING,
              TEMPERATURE_SHUTDOWN,
              TEMPERATURE_THROTTLING_BELOW_VR_MIN
      })
      public @interface TemperatureSource {}
  
      /**
       * Device temperature types.
       */
      // These constants are also defined in android/os/enums.proto.
      // Any change to the types here or in the thermal hal should be made in the proto as well.
      /** Temperature of CPUs in Celsius. */
      public static final int DEVICE_TEMPERATURE_CPU = Constants.TemperatureType.CPU;
  
      /** Temperature of GPUs in Celsius. */
      public static final int DEVICE_TEMPERATURE_GPU = Constants.TemperatureType.GPU;
  
      /** Temperature of battery in Celsius. */
      public static final int DEVICE_TEMPERATURE_BATTERY = Constants.TemperatureType.BATTERY;
  
      /** Temperature of device skin in Celsius. */
      public static final int DEVICE_TEMPERATURE_SKIN = Constants.TemperatureType.SKIN;
  
      /** Get current temperature. */
      public static final int TEMPERATURE_CURRENT = 0;
  
      /** Get throttling temperature threshold. */
      public static final int TEMPERATURE_THROTTLING = 1;
  
      /** Get shutdown temperature threshold. */
      public static final int TEMPERATURE_SHUTDOWN = 2;
  
      /**
       * Get throttling temperature threshold above which minimum clockrates for VR mode will not be
       * met.
       */
      public static final int TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3;
  
      /** Undefined temperature constant. */
      public static final float UNDEFINED_TEMPERATURE = -Float.MAX_VALUE;
  
      /** Calling app context. */
      private final Context mContext;
  
      /** @hide */
      public HardwarePropertiesManager(Context context, IHardwarePropertiesManager service) {
          mContext = context;
          mService = service;
      }
  
      /**
       * Return an array of device temperatures in Celsius.
       *
       * @param type type of requested device temperature, one of {@link #DEVICE_TEMPERATURE_CPU},
       * {@link #DEVICE_TEMPERATURE_GPU}, {@link #DEVICE_TEMPERATURE_BATTERY} or {@link
       * #DEVICE_TEMPERATURE_SKIN}.
       * @param source source of requested device temperature, one of {@link #TEMPERATURE_CURRENT},
       * {@link #TEMPERATURE_THROTTLING}, {@link #TEMPERATURE_THROTTLING_BELOW_VR_MIN} or
       * {@link #TEMPERATURE_SHUTDOWN}.
       * @return an array of requested float device temperatures. Temperature equals to
       *         {@link #UNDEFINED_TEMPERATURE} if undefined.
       *         Empty if platform doesn't provide the queried temperature.
       *
       * @throws SecurityException if something other than the device owner or the current VR service
       *         tries to retrieve information provided by this service.
      */
      public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type,
              @TemperatureSource int source) {
          switch (type) {
              case DEVICE_TEMPERATURE_CPU:
              case DEVICE_TEMPERATURE_GPU:
              case DEVICE_TEMPERATURE_BATTERY:
              case DEVICE_TEMPERATURE_SKIN:
                  switch (source) {
                      case TEMPERATURE_CURRENT:
                      case TEMPERATURE_THROTTLING:
                      case TEMPERATURE_SHUTDOWN:
                      case TEMPERATURE_THROTTLING_BELOW_VR_MIN:
                          try {
                              return mService.getDeviceTemperatures(mContext.getOpPackageName(), type,
                                      source);
                          } catch (RemoteException e) {
                              throw e.rethrowFromSystemServer();
                          }
                      default:
                          Log.w(TAG, "Unknown device temperature source.");
                          return new float[0];
                  }
              default:
                  Log.w(TAG, "Unknown device temperature type.");
                  return new float[0];
          }
      }
  
      /**
       * Return an array of CPU usage info for each core.
       *
       * @return an array of {@link android.os.CpuUsageInfo} for each core. Return {@code null} for
       *         each unplugged core.
       *         Empty if CPU usage is not supported on this system.
       *
       * @throws SecurityException if something other than the device owner or the current VR service
       *         tries to retrieve information provided by this service.
       */
      public @NonNull CpuUsageInfo[] getCpuUsages() {
          try {
              return mService.getCpuUsages(mContext.getOpPackageName());
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Return an array of fan speeds in RPM.
       *
       * @return an array of float fan speeds in RPM. Empty if there are no fans or fan speed is not
       * supported on this system.
       *
       * @throws SecurityException if something other than the device owner or the current VR service
       *         tries to retrieve information provided by this service.
       */
      public @NonNull float[] getFanSpeeds() {
          try {
              return mService.getFanSpeeds(mContext.getOpPackageName());
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  }
  