/*
 * Copyright (C) 2018 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.server.power;

import android.annotation.Nullable;
import android.content.Context;
import android.hardware.thermal.V1_0.ThermalStatus;
import android.hardware.thermal.V1_0.ThermalStatusCode;
import android.hardware.thermal.V1_1.IThermalCallback;
import android.hardware.thermal.V2_0.IThermalChangedCallback;
import android.hardware.thermal.V2_0.ThrottlingSeverity;
import android.os.Binder;
import android.os.CoolingDevice;
import android.os.HwBinder;
import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.IThermalStatusListener;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.Temperature;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.SystemService;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * This is a system service that listens to HAL thermal events and dispatch those to listeners.
 * <p>The service will also trigger actions based on severity of the throttling status.</p>
 *
 * @hide
 */
public class ThermalManagerService extends SystemService {
    private static final String TAG = ThermalManagerService.class.getSimpleName();

    /** Lock to protect listen list. */
    private final Object mLock = new Object();

    /**
     * Registered observers of the thermal events. Cookie is used to store type as Integer, null
     * means no filter.
     */
    @GuardedBy("mLock")
    private final RemoteCallbackList<IThermalEventListener> mThermalEventListeners =
            new RemoteCallbackList<>();

    /** Registered observers of the thermal status. */
    @GuardedBy("mLock")
    private final RemoteCallbackList<IThermalStatusListener> mThermalStatusListeners =
            new RemoteCallbackList<>();

    /** Current thermal status */
    @GuardedBy("mLock")
    private int mStatus;

    /** If override status takes effect*/
    @GuardedBy("mLock")
    private boolean mIsStatusOverride;

    /** Current thermal map, key as name */
    @GuardedBy("mLock")
    private ArrayMap<String, Temperature> mTemperatureMap = new ArrayMap<>();

    /** HAL wrapper. */
    private ThermalHalWrapper mHalWrapper;

    /** Hal ready. */
    private final AtomicBoolean mHalReady = new AtomicBoolean();

    /** Invalid throttling status */
    private static final int INVALID_THROTTLING = Integer.MIN_VALUE;

    public ThermalManagerService(Context context) {
        this(context, null);
    }

    @VisibleForTesting
    ThermalManagerService(Context context, @Nullable ThermalHalWrapper halWrapper) {
        super(context);
        mHalWrapper = halWrapper;
        // Initialize to invalid to send status onActivityManagerReady
        mStatus = INVALID_THROTTLING;
    }

    @Override
    public void onStart() {
        publishBinderService(Context.THERMAL_SERVICE, mService);
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
            onActivityManagerReady();
        }
    }

    private void onActivityManagerReady() {
        synchronized (mLock) {
            // Connect to HAL and post to listeners.
            boolean halConnected = (mHalWrapper != null);
            if (!halConnected) {
                mHalWrapper = new ThermalHal20Wrapper();
                halConnected = mHalWrapper.connectToHal();
            }
            if (!halConnected) {
                mHalWrapper = new ThermalHal11Wrapper();
                halConnected = mHalWrapper.connectToHal();
            }
            if (!halConnected) {
                mHalWrapper = new ThermalHal10Wrapper();
                halConnected = mHalWrapper.connectToHal();
            }
            mHalWrapper.setCallback(this::onTemperatureChangedCallback);
            if (!halConnected) {
                return;
            }
            List<Temperature> temperatures = mHalWrapper.getCurrentTemperatures(false,
                    0);
            final int count = temperatures.size();
            for (int i = 0; i < count; i++) {
                onTemperatureChanged(temperatures.get(i), false);
            }
            onTemperatureMapChangedLocked();
            mHalReady.set(true);
        }
    }

    private void postStatusListener(IThermalStatusListener listener) {
        final boolean thermalCallbackQueued = FgThread.getHandler().post(() -> {
            try {
                listener.onStatusChange(mStatus);
            } catch (RemoteException | RuntimeException e) {
                Slog.e(TAG, "Thermal callback failed to call", e);
            }
        });
        if (!thermalCallbackQueued) {
            Slog.e(TAG, "Thermal callback failed to queue");
        }
    }

    private void notifyStatusListenersLocked() {
        if (!Temperature.isValidStatus(mStatus)) {
            return;
        }
        final int length = mThermalStatusListeners.beginBroadcast();
        try {
            for (int i = 0; i < length; i++) {
                final IThermalStatusListener listener =
                        mThermalStatusListeners.getBroadcastItem(i);
                postStatusListener(listener);
            }
        } finally {
            mThermalStatusListeners.finishBroadcast();
        }
    }

    private void onTemperatureMapChangedLocked() {
        int newStatus = INVALID_THROTTLING;
        final int count = mTemperatureMap.size();
        for (int i = 0; i < count; i++) {
            Temperature t = mTemperatureMap.valueAt(i);
            if (t.getStatus() >= newStatus) {
                newStatus = t.getStatus();
            }
        }
        // Do not update if override from shell
        if (!mIsStatusOverride) {
            setStatusLocked(newStatus);
        }
    }

    private void setStatusLocked(int newStatus) {
        if (newStatus != mStatus) {
            mStatus = newStatus;
            notifyStatusListenersLocked();
        }
    }

    private void postEventListenerCurrentTemperatures(IThermalEventListener listener,
            @Nullable Integer type) {
        synchronized (mLock) {
            final int count = mTemperatureMap.size();
            for (int i = 0; i < count; i++) {
                postEventListener(mTemperatureMap.valueAt(i), listener,
                        type);
            }
        }
    }

    private void postEventListener(Temperature temperature,
            IThermalEventListener listener,
            @Nullable Integer type) {
        // Skip if listener registered with a different type
        if (type != null && type != temperature.getType()) {
            return;
        }
        final boolean thermalCallbackQueued = FgThread.getHandler().post(() -> {
            try {
                listener.notifyThrottling(temperature);
            } catch (RemoteException | RuntimeException e) {
                Slog.e(TAG, "Thermal callback failed to call", e);
            }
        });
        if (!thermalCallbackQueued) {
            Slog.e(TAG, "Thermal callback failed to queue");
        }
    }

    private void notifyEventListenersLocked(Temperature temperature) {
        final int length = mThermalEventListeners.beginBroadcast();
        try {
            for (int i = 0; i < length; i++) {
                final IThermalEventListener listener =
                        mThermalEventListeners.getBroadcastItem(i);
                final Integer type =
                        (Integer) mThermalEventListeners.getBroadcastCookie(i);
                postEventListener(temperature, listener, type);
            }
        } finally {
            mThermalEventListeners.finishBroadcast();
        }
        EventLog.writeEvent(EventLogTags.THERMAL_CHANGED, temperature.getName(),
                temperature.getType(), temperature.getValue(), temperature.getStatus(), mStatus);
    }

    private void shutdownIfNeeded(Temperature temperature) {
        if (temperature.getStatus() != Temperature.THROTTLING_SHUTDOWN) {
            return;
        }
        final PowerManager powerManager = getContext().getSystemService(PowerManager.class);
        switch (temperature.getType()) {
            case Temperature.TYPE_CPU:
                // Fall through
            case Temperature.TYPE_GPU:
                // Fall through
            case Temperature.TYPE_NPU:
                // Fall through
            case Temperature.TYPE_SKIN:
                powerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
                break;
            case Temperature.TYPE_BATTERY:
                powerManager.shutdown(false, PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE, false);
                break;
        }
    }

    private void onTemperatureChanged(Temperature temperature, boolean sendStatus) {
        shutdownIfNeeded(temperature);
        synchronized (mLock) {
            Temperature old = mTemperatureMap.put(temperature.getName(), temperature);
            if (old != null) {
                if (old.getStatus() != temperature.getStatus()) {
                    notifyEventListenersLocked(temperature);
                }
            } else {
                notifyEventListenersLocked(temperature);
            }
            if (sendStatus) {
                onTemperatureMapChangedLocked();
            }
        }
    }

    /* HwBinder callback **/
    private void onTemperatureChangedCallback(Temperature temperature) {
        final long token = Binder.clearCallingIdentity();
        try {
            onTemperatureChanged(temperature, true);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @VisibleForTesting
    final IThermalService.Stub mService = new IThermalService.Stub() {
        @Override
        public boolean registerThermalEventListener(IThermalEventListener listener) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            synchronized (mLock) {
                final long token = Binder.clearCallingIdentity();
                try {
                    if (!mThermalEventListeners.register(listener, null)) {
                        return false;
                    }
                    // Notify its callback after new client registered.
                    postEventListenerCurrentTemperatures(listener, null);
                    return true;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public boolean registerThermalEventListenerWithType(IThermalEventListener listener,
                int type) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            synchronized (mLock) {
                final long token = Binder.clearCallingIdentity();
                try {
                    if (!mThermalEventListeners.register(listener, new Integer(type))) {
                        return false;
                    }
                    // Notify its callback after new client registered.
                    postEventListenerCurrentTemperatures(listener, new Integer(type));
                    return true;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public boolean unregisterThermalEventListener(IThermalEventListener listener) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            synchronized (mLock) {
                final long token = Binder.clearCallingIdentity();
                try {
                    return mThermalEventListeners.unregister(listener);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public List<Temperature> getCurrentTemperatures() {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            final long token = Binder.clearCallingIdentity();
            try {
                if (!mHalReady.get()) {
                    return new ArrayList<>();
                }
                return mHalWrapper.getCurrentTemperatures(false, 0 /* not used */);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public List<Temperature> getCurrentTemperaturesWithType(int type) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            final long token = Binder.clearCallingIdentity();
            try {
                if (!mHalReady.get()) {
                    return new ArrayList<>();
                }
                return mHalWrapper.getCurrentTemperatures(true, type);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean registerThermalStatusListener(IThermalStatusListener listener) {
            synchronized (mLock) {
                // Notify its callback after new client registered.
                final long token = Binder.clearCallingIdentity();
                try {
                    if (!mThermalStatusListeners.register(listener)) {
                        return false;
                    }
                    // Notify its callback after new client registered.
                    postStatusListener(listener);
                    return true;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public boolean unregisterThermalStatusListener(IThermalStatusListener listener) {
            synchronized (mLock) {
                final long token = Binder.clearCallingIdentity();
                try {
                    return mThermalStatusListeners.unregister(listener);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public int getCurrentThermalStatus() {
            synchronized (mLock) {
                final long token = Binder.clearCallingIdentity();
                try {
                    return Temperature.isValidStatus(mStatus) ? mStatus
                            : Temperature.THROTTLING_NONE;
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }

        @Override
        public List<CoolingDevice> getCurrentCoolingDevices() {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            final long token = Binder.clearCallingIdentity();
            try {
                if (!mHalReady.get()) {
                    return new ArrayList<>();
                }
                return mHalWrapper.getCurrentCoolingDevices(false, 0);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public List<CoolingDevice> getCurrentCoolingDevicesWithType(int type) {
            getContext().enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);
            final long token = Binder.clearCallingIdentity();
            try {
                if (!mHalReady.get()) {
                    return new ArrayList<>();
                }
                return mHalWrapper.getCurrentCoolingDevices(true, type);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        private void dumpItemsLocked(PrintWriter pw, String prefix,
                Collection<?> items) {
            for (Iterator iterator = items.iterator(); iterator.hasNext();) {
                pw.println(prefix + iterator.next().toString());
            }
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    pw.println("IsStatusOverride: " + mIsStatusOverride);
                    pw.println("ThermalEventListeners:");
                    mThermalEventListeners.dump(pw, "\t");
                    pw.println("ThermalStatusListeners:");
                    mThermalStatusListeners.dump(pw, "\t");
                    pw.println("Thermal Status: " + mStatus);
                    pw.println("Cached temperatures:");
                    dumpItemsLocked(pw, "\t", mTemperatureMap.values());
                    pw.println("HAL Ready: " + mHalReady.get());
                    if (mHalReady.get()) {
                        pw.println("HAL connection:");
                        mHalWrapper.dump(pw, "\t");
                        pw.println("Current temperatures from HAL:");
                        dumpItemsLocked(pw, "\t",
                                mHalWrapper.getCurrentTemperatures(false, 0));
                        pw.println("Current cooling devices from HAL:");
                        dumpItemsLocked(pw, "\t",
                                mHalWrapper.getCurrentCoolingDevices(false, 0));
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        private boolean isCallerShell() {
            final int callingUid = Binder.getCallingUid();
            return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
        }

        @Override
        public void onShellCommand(FileDescriptor in, FileDescriptor out,
                FileDescriptor err, String[] args, ShellCallback callback,
                ResultReceiver resultReceiver) {
            if (!isCallerShell()) {
                Slog.w(TAG, "Only shell is allowed to call thermalservice shell commands");
                return;
            }
            (new ThermalShellCommand()).exec(
                    this, in, out, err, args, callback, resultReceiver);
        }

    };

    class ThermalShellCommand extends ShellCommand {
        @Override
        public int onCommand(String cmd) {
            switch(cmd != null ? cmd : "") {
                case "override-status":
                    return runOverrideStatus();
                case "reset":
                    return runReset();
                default:
                    return handleDefaultCommands(cmd);
            }
        }

        private int runReset() {
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mLock) {
                    mIsStatusOverride = false;
                    onTemperatureMapChangedLocked();
                    return 0;
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        private int runOverrideStatus() {
            final long token = Binder.clearCallingIdentity();
            try {
                final PrintWriter pw = getOutPrintWriter();
                int status;
                try {
                    status = Integer.parseInt(getNextArgRequired());
                } catch (RuntimeException ex) {
                    pw.println("Error: " + ex.toString());
                    return -1;
                }
                if (!Temperature.isValidStatus(status)) {
                    pw.println("Invalid status: " + status);
                    return -1;
                }
                synchronized (mLock) {
                    mIsStatusOverride = true;
                    setStatusLocked(status);
                }
                return 0;
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void onHelp() {
            final PrintWriter pw = getOutPrintWriter();
            pw.println("Thermal service (thermalservice) commands:");
            pw.println("  help");
            pw.println("    Print this help text.");
            pw.println("");
            pw.println("  override-status STATUS");
            pw.println("    sets and locks the thermal status of the device to STATUS.");
            pw.println("    status code is defined in android.os.Temperature.");
            pw.println("  reset");
            pw.println("    unlocks the thermal status of the device.");
            pw.println();
        }
    }

    abstract static class ThermalHalWrapper {
        protected static final String TAG = ThermalHalWrapper.class.getSimpleName();

        /** Lock to protect HAL handle. */
        protected final Object mHalLock = new Object();

        @FunctionalInterface
        interface TemperatureChangedCallback {
            void onValues(Temperature temperature);
        }

        /** Temperature callback. */
        protected TemperatureChangedCallback mCallback;

        /** Cookie for matching the right end point. */
        protected static final int THERMAL_HAL_DEATH_COOKIE = 5612;

        @VisibleForTesting
        protected void setCallback(TemperatureChangedCallback cb) {
            mCallback = cb;
        }

        protected abstract List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                int type);

        protected abstract List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter,
                int type);

        protected abstract boolean connectToHal();

        protected abstract void dump(PrintWriter pw, String prefix);

        protected void resendCurrentTemperatures() {
            synchronized (mHalLock) {
                List<Temperature> temperatures = getCurrentTemperatures(false, 0);
                final int count = temperatures.size();
                for (int i = 0; i < count; i++) {
                    mCallback.onValues(temperatures.get(i));
                }
            }
        }

        final class DeathRecipient implements HwBinder.DeathRecipient {
            @Override
            public void serviceDied(long cookie) {
                if (cookie == THERMAL_HAL_DEATH_COOKIE) {
                    Slog.e(TAG, "Thermal HAL service died cookie: " + cookie);
                    synchronized (mHalLock) {
                        connectToHal();
                        // Post to listeners after reconnect to HAL.
                        resendCurrentTemperatures();
                    }
                }
            }
        }
    }


    static class ThermalHal10Wrapper extends ThermalHalWrapper {
        /** Proxy object for the Thermal HAL 1.0 service. */
        @GuardedBy("mHalLock")
        private android.hardware.thermal.V1_0.IThermal mThermalHal10 = null;

        @Override
        protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<Temperature> ret = new ArrayList<>();
                if (mThermalHal10 == null) {
                    return ret;
                }
                try {
                    mThermalHal10.getTemperatures(
                            (ThermalStatus status,
                                    ArrayList<android.hardware.thermal.V1_0.Temperature>
                                            temperatures) -> {
                                if (ThermalStatusCode.SUCCESS == status.code) {
                                    for (android.hardware.thermal.V1_0.Temperature
                                            temperature : temperatures) {
                                        if (shouldFilter && type != temperature.type) {
                                            continue;
                                        }
                                        // Thermal HAL 1.0 doesn't report current throttling status
                                        ret.add(new Temperature(
                                                temperature.currentValue, temperature.type,
                                                temperature.name,
                                                Temperature.THROTTLING_NONE));
                                    }
                                } else {
                                    Slog.e(TAG,
                                            "Couldn't get temperatures because of HAL error: "
                                                    + status.debugMessage);
                                }

                            });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<CoolingDevice> ret = new ArrayList<>();
                if (mThermalHal10 == null) {
                    return ret;
                }
                try {
                    mThermalHal10.getCoolingDevices((status, coolingDevices) -> {
                        if (ThermalStatusCode.SUCCESS == status.code) {
                            for (android.hardware.thermal.V1_0.CoolingDevice
                                    coolingDevice : coolingDevices) {
                                if (shouldFilter && type != coolingDevice.type) {
                                    continue;
                                }
                                ret.add(new CoolingDevice(
                                        (long) coolingDevice.currentValue,
                                        coolingDevice.type,
                                        coolingDevice.name));
                            }
                        } else {
                            Slog.e(TAG,
                                    "Couldn't get cooling device because of HAL error: "
                                            + status.debugMessage);
                        }

                    });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentCoolingDevices, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected boolean connectToHal() {
            synchronized (mHalLock) {
                try {
                    mThermalHal10 = android.hardware.thermal.V1_0.IThermal.getService();
                    mThermalHal10.linkToDeath(new DeathRecipient(),
                            THERMAL_HAL_DEATH_COOKIE);
                    Slog.i(TAG,
                            "Thermal HAL 1.0 service connected, no thermal call back will be "
                                    + "called due to legacy API.");
                } catch (NoSuchElementException | RemoteException e) {
                    Slog.e(TAG,
                            "Thermal HAL 1.0 service not connected.");
                    mThermalHal10 = null;
                }
                return (mThermalHal10 != null);
            }
        }

        @Override
        protected void dump(PrintWriter pw, String prefix) {
            synchronized (mHalLock) {
                pw.print(prefix);
                pw.println("ThermalHAL 1.0 connected: " + (mThermalHal10 != null ? "yes"
                        : "no"));
            }
        }
    }

    static class ThermalHal11Wrapper extends ThermalHalWrapper {
        /** Proxy object for the Thermal HAL 1.1 service. */
        @GuardedBy("mHalLock")
        private android.hardware.thermal.V1_1.IThermal mThermalHal11 = null;

        /** HWbinder callback for Thermal HAL 1.1. */
        private final IThermalCallback.Stub mThermalCallback11 =
                new IThermalCallback.Stub() {
                    @Override
                    public void notifyThrottling(boolean isThrottling,
                            android.hardware.thermal.V1_0.Temperature temperature) {
                        Temperature thermalSvcTemp = new Temperature(
                                temperature.currentValue, temperature.type, temperature.name,
                                isThrottling ? ThrottlingSeverity.SEVERE
                                        : ThrottlingSeverity.NONE);
                        final long token = Binder.clearCallingIdentity();
                        try {
                            mCallback.onValues(thermalSvcTemp);
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
                    }
                };

        @Override
        protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<Temperature> ret = new ArrayList<>();
                if (mThermalHal11 == null) {
                    return ret;
                }
                try {
                    mThermalHal11.getTemperatures(
                            (ThermalStatus status,
                                    ArrayList<android.hardware.thermal.V1_0.Temperature>
                                            temperatures) -> {
                                if (ThermalStatusCode.SUCCESS == status.code) {
                                    for (android.hardware.thermal.V1_0.Temperature
                                            temperature : temperatures) {
                                        if (shouldFilter && type != temperature.type) {
                                            continue;
                                        }
                                        // Thermal HAL 1.1 doesn't report current throttling status
                                        ret.add(new Temperature(
                                                temperature.currentValue, temperature.type,
                                                temperature.name,
                                                Temperature.THROTTLING_NONE));
                                    }
                                } else {
                                    Slog.e(TAG,
                                            "Couldn't get temperatures because of HAL error: "
                                                    + status.debugMessage);
                                }

                            });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<CoolingDevice> ret = new ArrayList<>();
                if (mThermalHal11 == null) {
                    return ret;
                }
                try {
                    mThermalHal11.getCoolingDevices((status, coolingDevices) -> {
                        if (ThermalStatusCode.SUCCESS == status.code) {
                            for (android.hardware.thermal.V1_0.CoolingDevice
                                    coolingDevice : coolingDevices) {
                                if (shouldFilter && type != coolingDevice.type) {
                                    continue;
                                }
                                ret.add(new CoolingDevice(
                                        (long) coolingDevice.currentValue,
                                        coolingDevice.type,
                                        coolingDevice.name));
                            }
                        } else {
                            Slog.e(TAG,
                                    "Couldn't get cooling device because of HAL error: "
                                            + status.debugMessage);
                        }

                    });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentCoolingDevices, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected boolean connectToHal() {
            synchronized (mHalLock) {
                try {
                    mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService();
                    mThermalHal11.linkToDeath(new DeathRecipient(),
                            THERMAL_HAL_DEATH_COOKIE);
                    mThermalHal11.registerThermalCallback(mThermalCallback11);
                    Slog.i(TAG, "Thermal HAL 1.1 service connected, limited thermal functions "
                            + "due to legacy API.");
                } catch (NoSuchElementException | RemoteException e) {
                    Slog.e(TAG, "Thermal HAL 1.1 service not connected.");
                    mThermalHal11 = null;
                }
                return (mThermalHal11 != null);
            }
        }

        @Override
        protected void dump(PrintWriter pw, String prefix) {
            synchronized (mHalLock) {
                pw.print(prefix);
                pw.println("ThermalHAL 1.1 connected: " + (mThermalHal11 != null ? "yes"
                        : "no"));
            }
        }
    }

    static class ThermalHal20Wrapper extends ThermalHalWrapper {
        /** Proxy object for the Thermal HAL 2.0 service. */
        @GuardedBy("mHalLock")
        private android.hardware.thermal.V2_0.IThermal mThermalHal20 = null;

        /** HWbinder callback for Thermal HAL 2.0. */
        private final IThermalChangedCallback.Stub mThermalCallback20 =
                new IThermalChangedCallback.Stub() {
                    @Override
                    public void notifyThrottling(
                            android.hardware.thermal.V2_0.Temperature temperature) {
                        Temperature thermalSvcTemp = new Temperature(
                                temperature.value, temperature.type, temperature.name,
                                temperature.throttlingStatus);
                        final long token = Binder.clearCallingIdentity();
                        try {
                            mCallback.onValues(thermalSvcTemp);
                        } finally {
                            Binder.restoreCallingIdentity(token);
                        }
                    }
                };

        @Override
        protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<Temperature> ret = new ArrayList<>();
                if (mThermalHal20 == null) {
                    return ret;
                }
                try {
                    mThermalHal20.getCurrentTemperatures(shouldFilter, type,
                            (status, temperatures) -> {
                                if (ThermalStatusCode.SUCCESS == status.code) {
                                    for (android.hardware.thermal.V2_0.Temperature
                                            temperature : temperatures) {
                                        ret.add(new Temperature(
                                                temperature.value, temperature.type,
                                                temperature.name,
                                                temperature.throttlingStatus));
                                    }
                                } else {
                                    Slog.e(TAG,
                                            "Couldn't get temperatures because of HAL error: "
                                                    + status.debugMessage);
                                }

                            });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter,
                int type) {
            synchronized (mHalLock) {
                List<CoolingDevice> ret = new ArrayList<>();
                if (mThermalHal20 == null) {
                    return ret;
                }
                try {
                    mThermalHal20.getCurrentCoolingDevices(shouldFilter, type,
                            (status, coolingDevices) -> {
                                if (ThermalStatusCode.SUCCESS == status.code) {
                                    for (android.hardware.thermal.V2_0.CoolingDevice
                                            coolingDevice : coolingDevices) {
                                        ret.add(new CoolingDevice(
                                                coolingDevice.value, coolingDevice.type,
                                                coolingDevice.name));
                                    }
                                } else {
                                    Slog.e(TAG,
                                            "Couldn't get cooling device because of HAL error: "
                                                    + status.debugMessage);
                                }

                            });
                } catch (RemoteException e) {
                    Slog.e(TAG, "Couldn't getCurrentCoolingDevices, reconnecting...", e);
                    connectToHal();
                }
                return ret;
            }
        }

        @Override
        protected boolean connectToHal() {
            synchronized (mHalLock) {
                try {
                    mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService();
                    mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
                    mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
                            0 /* not used */);
                    Slog.i(TAG, "Thermal HAL 2.0 service connected.");
                } catch (NoSuchElementException | RemoteException e) {
                    Slog.e(TAG, "Thermal HAL 2.0 service not connected.");
                    mThermalHal20 = null;
                }
                return (mThermalHal20 != null);
            }
        }

        @Override
        protected void dump(PrintWriter pw, String prefix) {
            synchronized (mHalLock) {
                pw.print(prefix);
                pw.println("ThermalHAL 2.0 connected: " + (mThermalHal20 != null ? "yes"
                        : "no"));
            }
        }
    }

}
