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