From f8754ac2127f8adf40bd4731f39b16340acdb2f7 Mon Sep 17 00:00:00 2001 From: Polina Bondarenko Date: Fri, 12 Feb 2016 20:38:23 +0100 Subject: [PATCH] Added hardwareproperties SystemService Add HardwarePropertiesManagerService which call native methods to get CPU, GPU, battery temperatures, CPU usage info, fan speeds. Restrict hardware properties retrieval only for device and profile owners. Bug: 26945055 Change-Id: I4d6b30b78e575532d5e9cfa59ef6cd81355439d4 --- Android.mk | 1 + .../android/app/SystemServiceRegistry.java | 10 +- core/java/android/os/CpuUsageInfo.aidl | 18 ++++ .../android/os/HardwarePropertiesManager.java | 48 ++++++--- .../os/IHardwarePropertiesManager.aidl | 28 ++++++ core/jni/Android.mk | 3 +- core/jni/AndroidRuntime.cpp | 2 - .../HardwarePropertiesManagerService.java | 99 +++++++++++++++++++ services/core/jni/Android.mk | 1 + ...erver_HardwarePropertiesManagerService.cpp | 12 +-- services/core/jni/onload.cpp | 2 + .../java/com/android/server/SystemServer.java | 12 +++ 12 files changed, 212 insertions(+), 24 deletions(-) create mode 100644 core/java/android/os/CpuUsageInfo.aidl create mode 100644 core/java/android/os/IHardwarePropertiesManager.aidl create mode 100644 services/core/java/com/android/server/HardwarePropertiesManagerService.java rename core/jni/android_os_HardwarePropertiesManager.cpp => services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp (94%) diff --git a/Android.mk b/Android.mk index 6ec434cfbf544..b49d0793802c2 100644 --- a/Android.mk +++ b/Android.mk @@ -215,6 +215,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ core/java/android/os/IDeviceIdleController.aidl \ + core/java/android/os/IHardwarePropertiesManager.aidl \ core/java/android/os/IMaintenanceActivityListener.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkActivityListener.aidl \ diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 5eed781d76c36..52fba3b7b840c 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -89,6 +89,7 @@ import android.os.BatteryManager; import android.os.DropBoxManager; import android.os.HardwarePropertiesManager; import android.os.IBinder; +import android.os.IHardwarePropertiesManager; import android.os.IPowerManager; import android.os.IUserManager; import android.os.PowerManager; @@ -715,7 +716,14 @@ final class SystemServiceRegistry { new CachedServiceFetcher() { @Override public HardwarePropertiesManager createService(ContextImpl ctx) { - return new HardwarePropertiesManager(); + IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE); + IHardwarePropertiesManager service = + IHardwarePropertiesManager.Stub.asInterface(b); + if (service == null) { + Log.wtf(TAG, "Failed to get hardwareproperties service."); + return null; + } + return new HardwarePropertiesManager(ctx, service); }}); registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class, diff --git a/core/java/android/os/CpuUsageInfo.aidl b/core/java/android/os/CpuUsageInfo.aidl new file mode 100644 index 0000000000000..f81aefe4423f7 --- /dev/null +++ b/core/java/android/os/CpuUsageInfo.aidl @@ -0,0 +1,18 @@ +/* Copyright 2016, 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 android.os; + +parcelable CpuUsageInfo; diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java index bc317b672d9cf..c72a6481ebedb 100644 --- a/core/java/android/os/HardwarePropertiesManager.java +++ b/core/java/android/os/HardwarePropertiesManager.java @@ -17,10 +17,12 @@ package android.os; import android.annotation.IntDef; import android.annotation.NonNull; +import android.content.Context; +import android.util.Log; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; - /** * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc. @@ -29,11 +31,7 @@ public class HardwarePropertiesManager { private static final String TAG = HardwarePropertiesManager.class.getSimpleName(); - private static native void nativeInit(); - - private static native float[] nativeGetFanSpeeds(); - private static native float[] nativeGetDeviceTemperatures(int type); - private static native CpuUsageInfo[] nativeGetCpuUsages(); + private final IHardwarePropertiesManager mService; @Retention(RetentionPolicy.SOURCE) @IntDef({ @@ -54,9 +52,13 @@ public class HardwarePropertiesManager { /** Temperature of battery in Celsius. */ public static final int DEVICE_TEMPERATURE_BATTERY = 2; + /** Calling app context. */ + private final Context mContext; + /** @hide */ - public HardwarePropertiesManager() { - nativeInit(); + public HardwarePropertiesManager(Context context, IHardwarePropertiesManager service) { + mContext = context; + mService = service; } /** @@ -68,13 +70,19 @@ public class HardwarePropertiesManager { * Empty if platform doesn't provide the queried temperature. * * @throws IllegalArgumentException if an incorrect temperature type is queried. + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) { switch (type) { case DEVICE_TEMPERATURE_CPU: case DEVICE_TEMPERATURE_GPU: case DEVICE_TEMPERATURE_BATTERY: - return nativeGetDeviceTemperatures(type); + try { + return mService.getDeviceTemperatures(mContext.getOpPackageName(), type); + } catch (RemoteException e) { + Log.w(TAG, "Could not get device temperatures", e); + return new float[0]; + } default: throw new IllegalArgumentException(); } @@ -85,18 +93,32 @@ public class HardwarePropertiesManager { * * @return an array of {@link android.os.CpuUsageInfo} for each core. * Empty if CPU usage is not supported on this system. + * + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull CpuUsageInfo[] getCpuUsages() { - return nativeGetCpuUsages(); + try { + return mService.getCpuUsages(mContext.getOpPackageName()); + } catch (RemoteException e) { + Log.w(TAG, "Could not get CPU usages", e); + return new CpuUsageInfo[0]; + } } /** * Return an array of fan speeds in RPM. * - * @return an arrat of float fan speeds. Empty if there is no fans or fan speed - * not supported on this system. + * @return an array of float fan speeds in RPM. Empty if there are no fans or fan speed is not + * supported on this system. + * + * @throws SecurityException if a non profile or device owner tries to call this method. */ public @NonNull float[] getFanSpeeds() { - return nativeGetFanSpeeds(); + try { + return mService.getFanSpeeds(mContext.getOpPackageName()); + } catch (RemoteException e) { + Log.w(TAG, "Could not get fan speeds", e); + return new float[0]; + } } } diff --git a/core/java/android/os/IHardwarePropertiesManager.aidl b/core/java/android/os/IHardwarePropertiesManager.aidl new file mode 100644 index 0000000000000..bcf0dc85a5e16 --- /dev/null +++ b/core/java/android/os/IHardwarePropertiesManager.aidl @@ -0,0 +1,28 @@ +/* +** +** Copyright 2016, 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 android.os; + +import android.os.CpuUsageInfo; + +/** @hide */ + +interface IHardwarePropertiesManager { + float[] getDeviceTemperatures(String callingPackage, int type); + CpuUsageInfo[] getCpuUsages(String callingPackage); + float[] getFanSpeeds(String callingPackage); +} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 1b6b53ae49f4f..8b686b70041d7 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -177,8 +177,7 @@ LOCAL_SRC_FILES:= \ com_android_internal_net_NetworkStatsFactory.cpp \ com_android_internal_os_Zygote.cpp \ com_android_internal_util_VirtualRefBasePtr.cpp \ - com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \ - android_os_HardwarePropertiesManager.cpp + com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 223fc1af46d51..017fb533723c4 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -198,7 +198,6 @@ extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env); extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); -extern int register_android_os_HardwarePropertiesManager(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1390,7 +1389,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_animation_PropertyValuesHolder), REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_net_NetworkStatsFactory), - REG_JNI(register_android_os_HardwarePropertiesManager), }; diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java new file mode 100644 index 0000000000000..cc21e99371e4f --- /dev/null +++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 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; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.CpuUsageInfo; +import android.os.IHardwarePropertiesManager; + +import java.util.Arrays; + +/** + * Service for {@link HardwarePropertiesManager} + */ +public class HardwarePropertiesManagerService extends IHardwarePropertiesManager.Stub { + + private static native void nativeInit(); + + private static native float[] nativeGetFanSpeeds(); + private static native float[] nativeGetDeviceTemperatures(int type); + private static native CpuUsageInfo[] nativeGetCpuUsages(); + + private final Context mContext; + private final Object mLock = new Object(); + + public HardwarePropertiesManagerService(Context context) { + mContext = context; + synchronized (mLock) { + nativeInit(); + } + } + + @Override + public float[] getDeviceTemperatures(String callingPackage, int type) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetDeviceTemperatures(type); + } + } + + @Override + public CpuUsageInfo[] getCpuUsages(String callingPackage) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetCpuUsages(); + } + } + + @Override + public float[] getFanSpeeds(String callingPackage) throws SecurityException { + enforceHardwarePropertiesRetrievalAllowed(callingPackage); + synchronized (mLock) { + return nativeGetFanSpeeds(); + } + } + + /** + * Throws SecurityException if the calling package is not allowed to retrieve information + * provided by the service. + * + * @param callingPackage The calling package name. + * + * @throws SecurityException if a non profile or device owner tries to retrieve information + * provided by the service. + */ + private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage) + throws SecurityException { + final PackageManager pm = mContext.getPackageManager(); + try { + final int uid = pm.getPackageUid(callingPackage, 0); + if (Binder.getCallingUid() != uid) { + throw new SecurityException("The caller has faked the package name."); + } + } catch (PackageManager.NameNotFoundException e) { + throw new SecurityException("The caller has faked the package name."); + } + + final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + if (!dpm.isDeviceOwnerApp(callingPackage) && !dpm.isProfileOwnerApp(callingPackage)) { + throw new SecurityException("The caller is not a device or profile owner."); + } + } +} diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index bb571c3d06314..5e5c6d9321e3b 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -17,6 +17,7 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ diff --git a/core/jni/android_os_HardwarePropertiesManager.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp similarity index 94% rename from core/jni/android_os_HardwarePropertiesManager.cpp rename to services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp index dc1ba48097b8f..214d9882c499d 100644 --- a/core/jni/android_os_HardwarePropertiesManager.cpp +++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "HardwarePropertiesManager-JNI" +#define LOG_TAG "HardwarePropertiesManagerService-JNI" #include "JNIHelp.h" #include "jni.h" @@ -137,7 +137,7 @@ static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) { // ---------------------------------------------------------------------------- -static const JNINativeMethod gHardwarePropertiesManagerMethods[] = { +static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "()V", (void*) nativeInit }, @@ -149,11 +149,11 @@ static const JNINativeMethod gHardwarePropertiesManagerMethods[] = { (void*) nativeGetCpuUsages } }; -int register_android_os_HardwarePropertiesManager(JNIEnv* env) { +int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) { gHardwarePropertiesModule = nullptr; - int res = jniRegisterNativeMethods(env, "android/os/HardwarePropertiesManager", - gHardwarePropertiesManagerMethods, - NELEM(gHardwarePropertiesManagerMethods)); + int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService", + gHardwarePropertiesManagerServiceMethods, + NELEM(gHardwarePropertiesManagerServiceMethods)); jclass clazz = env->FindClass("android/os/CpuUsageInfo"); gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz, diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index ef5c56c1bcfad..be99673a4cb50 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -44,6 +44,7 @@ int register_android_server_hdmi_HdmiCecController(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); int register_android_server_PersistentDataBlockService(JNIEnv* env); int register_android_server_Watchdog(JNIEnv* env); +int register_android_server_HardwarePropertiesManagerService(JNIEnv* env); }; using namespace android; @@ -83,6 +84,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_tv_TvInputHal(env); register_android_server_PersistentDataBlockService(env); register_android_server_Watchdog(env); + register_android_server_HardwarePropertiesManagerService(env); return JNI_VERSION_1_4; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 0cf93288714f8..511c1e76943fe 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -488,6 +488,7 @@ public final class SystemServer { MmsServiceBroker mmsService = null; EntropyMixer entropyMixer = null; VrManagerService vrManagerService = null; + HardwarePropertiesManagerService hardwarePropertiesService = null; boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false); boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false); @@ -962,6 +963,17 @@ public final class SystemServer { Slog.e(TAG, "Failure starting SerialService", e); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); + + Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, + "StartHardwarePropertiesManagerService"); + try { + hardwarePropertiesService = new HardwarePropertiesManagerService(context); + ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE, + hardwarePropertiesService); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } mSystemServiceManager.startService(TwilightService.class);