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 android.Manifest;
20import android.app.ActivityManager;
21import android.app.admin.DevicePolicyManager;
22import android.content.Context;
23import android.content.pm.PackageManager;
24import android.os.Binder;
25import android.os.CpuUsageInfo;
26import android.os.IHardwarePropertiesManager;
27import android.os.Process;
28import android.os.UserHandle;
29import com.android.server.vr.VrManagerInternal;
30
31import java.util.Arrays;
32
33/**
34 * Service for {@link HardwarePropertiesManager}
35 */
36public class HardwarePropertiesManagerService extends IHardwarePropertiesManager.Stub {
37
38    private static native void nativeInit();
39
40    private static native float[] nativeGetFanSpeeds();
41    private static native float[] nativeGetDeviceTemperatures(int type, int source);
42    private static native CpuUsageInfo[] nativeGetCpuUsages();
43
44    private final Context mContext;
45    private final Object mLock = new Object();
46
47    public HardwarePropertiesManagerService(Context context) {
48        mContext = context;
49        synchronized (mLock) {
50            nativeInit();
51        }
52    }
53
54    @Override
55    public float[] getDeviceTemperatures(String callingPackage, int type, int source)
56            throws SecurityException {
57        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
58        synchronized (mLock) {
59            return nativeGetDeviceTemperatures(type, source);
60        }
61    }
62
63    @Override
64    public CpuUsageInfo[] getCpuUsages(String callingPackage) throws SecurityException {
65        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
66        synchronized (mLock) {
67            return nativeGetCpuUsages();
68        }
69    }
70
71    @Override
72    public float[] getFanSpeeds(String callingPackage) throws SecurityException {
73        enforceHardwarePropertiesRetrievalAllowed(callingPackage);
74        synchronized (mLock) {
75            return nativeGetFanSpeeds();
76        }
77    }
78
79    /**
80     * Throws SecurityException if the calling package is not allowed to retrieve information
81     * provided by the service.
82     *
83     * @param callingPackage The calling package name.
84     *
85     * @throws SecurityException if something other than the device owner, the current VR service,
86     *         or a caller holding the {@link Manifest.permission#DEVICE_POWER} permission tries to
87     *         retrieve information provided by this service.
88     */
89    private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage)
90            throws SecurityException {
91        final PackageManager pm = mContext.getPackageManager();
92        int uid = 0;
93        try {
94            uid = pm.getPackageUid(callingPackage, 0);
95            if (Binder.getCallingUid() != uid) {
96                throw new SecurityException("The caller has faked the package name.");
97            }
98        } catch (PackageManager.NameNotFoundException e) {
99            throw new SecurityException("The caller has faked the package name.");
100        }
101
102        final int userId = UserHandle.getUserId(uid);
103        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
104        final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
105        if (!dpm.isDeviceOwnerApp(callingPackage)
106                && !vrService.isCurrentVrListener(callingPackage, userId)
107                && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
108                        != PackageManager.PERMISSION_GRANTED) {
109            throw new SecurityException("The caller is not a device owner, bound VrListenerService"
110                + ", or holding the DEVICE_POWER permission.");
111        }
112    }
113}
114