1/*
2 * Copyright (C) 2016 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.server;
18
19import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY;
20import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU;
21import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU;
22import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN;
23import static android.os.HardwarePropertiesManager.TEMPERATURE_CURRENT;
24import static android.os.HardwarePropertiesManager.TEMPERATURE_SHUTDOWN;
25import static android.os.HardwarePropertiesManager.TEMPERATURE_THROTTLING;
26import static android.os.HardwarePropertiesManager.TEMPERATURE_THROTTLING_BELOW_VR_MIN;
27
28import android.Manifest;
29import android.app.ActivityManager;
30import android.app.AppOpsManager;
31import android.app.admin.DevicePolicyManager;
32import android.content.Context;
33import android.content.pm.PackageManager;
34import android.os.Binder;
35import android.os.CpuUsageInfo;
36import android.os.IHardwarePropertiesManager;
37import android.os.Process;
38import android.os.UserHandle;
39import com.android.internal.util.DumpUtils;
40import com.android.server.vr.VrManagerInternal;
41
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.util.Arrays;
45
46/**
47 * Service for {@link HardwarePropertiesManager}
48 */
49public class HardwarePropertiesManagerService extends IHardwarePropertiesManager.Stub {
50
51    private static final String TAG = "HardwarePropertiesManagerService";
52    private static native void nativeInit();
53
54    private static native float[] nativeGetFanSpeeds();
55    private static native float[] nativeGetDeviceTemperatures(int type, int source);
56    private static native CpuUsageInfo[] nativeGetCpuUsages();
57
58    private final Context mContext;
59    private final Object mLock = new Object();
60    private final AppOpsManager mAppOps;
61
62    public HardwarePropertiesManagerService(Context context) {
63        mContext = context;
64        mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
65        synchronized (mLock) {
66            nativeInit();
67        }
68    }
69
70    // TODO - Make HardwarePropertiesManager APIs require a userId to verifiy
71    // cross user permission - b/63697518
72    @Override
73    public float[] getDeviceTemperatures(String callingPackage, int type, int source)
74            throws SecurityException {
75        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
76        synchronized (mLock) {
77            return nativeGetDeviceTemperatures(type, source);
78        }
79    }
80
81    // TODO - Make HardwarePropertiesManager APIs require a userId to verifiy
82    // cross user permission - b/63697518
83    @Override
84    public CpuUsageInfo[] getCpuUsages(String callingPackage) throws SecurityException {
85        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
86        synchronized (mLock) {
87            return nativeGetCpuUsages();
88        }
89    }
90
91    // TODO - Make HardwarePropertiesManager APIs require a userId to verifiy
92    // cross user permission - b/63697518
93    @Override
94    public float[] getFanSpeeds(String callingPackage) throws SecurityException {
95        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
96        synchronized (mLock) {
97            return nativeGetFanSpeeds();
98        }
99    }
100
101    private String getCallingPackageName() {
102        final String[] packages = mContext.getPackageManager().getPackagesForUid(
103                Binder.getCallingUid());
104        if (packages != null && packages.length > 0) {
105           return packages[0];
106        }
107        return "unknown";
108    }
109
110    private void dumpTempValues(String pkg, PrintWriter pw, int type,
111            String typeLabel) {
112        dumpTempValues(pkg, pw, type, typeLabel, "temperatures: ",
113                TEMPERATURE_CURRENT);
114        dumpTempValues(pkg, pw, type, typeLabel, "throttling temperatures: ",
115                TEMPERATURE_THROTTLING);
116        dumpTempValues(pkg, pw, type, typeLabel, "shutdown temperatures: ",
117                TEMPERATURE_SHUTDOWN);
118        dumpTempValues(pkg, pw, type, typeLabel, "vr throttling temperatures: ",
119                TEMPERATURE_THROTTLING_BELOW_VR_MIN);
120    }
121
122    private void dumpTempValues(String pkg, PrintWriter pw, int type,
123            String typeLabel, String subLabel, int valueType) {
124        pw.println(typeLabel + subLabel + Arrays.toString(getDeviceTemperatures(
125                pkg, type, valueType)));
126    }
127
128    @Override
129    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
130        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
131        pw.println("****** Dump of HardwarePropertiesManagerService ******");
132
133        final String PKG = getCallingPackageName();
134        dumpTempValues(PKG, pw, DEVICE_TEMPERATURE_CPU, "CPU ");
135        dumpTempValues(PKG, pw, DEVICE_TEMPERATURE_GPU, "GPU ");
136        dumpTempValues(PKG, pw, DEVICE_TEMPERATURE_BATTERY, "Battery ");
137        dumpTempValues(PKG, pw, DEVICE_TEMPERATURE_SKIN, "Skin ");
138
139        float[] fanSpeeds = getFanSpeeds(PKG);
140        pw.println("Fan speed: " + Arrays.toString(fanSpeeds) + "\n");
141
142        CpuUsageInfo[] cpuUsageInfos = getCpuUsages(PKG);
143        int core = 0;
144        for (int i = 0; i < cpuUsageInfos.length; i++) {
145            pw.println("Cpu usage of core: " + i +
146                    ", active = " + cpuUsageInfos[i].getActive() +
147                    ", total = " + cpuUsageInfos[i].getTotal());
148        }
149        pw.println("****** End of HardwarePropertiesManagerService dump ******");
150    }
151
152    /**
153     * Throws SecurityException if the calling package is not allowed to retrieve information
154     * provided by the service.
155     *
156     * @param callingPackage The calling package name.
157     *
158     * @throws SecurityException if something other than the device owner, the current VR service,
159     *         or a caller holding the {@link Manifest.permission#DEVICE_POWER} permission tries to
160     *         retrieve information provided by this service.
161     */
162    private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage)
163            throws SecurityException {
164        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
165        final int userId = UserHandle.getUserId(Binder.getCallingUid());
166        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
167        final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
168        if (!dpm.isDeviceOwnerApp(callingPackage)
169                && !vrService.isCurrentVrListener(callingPackage, userId)
170                && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
171                        != PackageManager.PERMISSION_GRANTED) {
172            throw new SecurityException("The caller is not a device owner, bound VrListenerService"
173                + ", or holding the DEVICE_POWER permission.");
174        }
175    }
176}
177
178
179