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