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
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 0000000..cc21e99
--- /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 bb571c3..5e5c6d9 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -17,6 +17,7 @@
$(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/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
new file mode 100644
index 0000000..214d988
--- /dev/null
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "HardwarePropertiesManagerService-JNI"
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <stdlib.h>
+
+#include <hardware/hardware_properties.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <hardware_properties/HardwarePropertiesManager.h>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+static struct {
+ jclass clazz;
+ jmethodID initMethod;
+} gCpuUsageInfoClassInfo;
+
+static struct hardware_properties_module* gHardwarePropertiesModule;
+
+// ----------------------------------------------------------------------------
+
+static void nativeInit(JNIEnv* env, jobject obj) {
+ status_t err = hw_get_module(HARDWARE_PROPERTIES_HARDWARE_MODULE_ID,
+ (hw_module_t const**)&gHardwarePropertiesModule);
+ if (err) {
+ ALOGE("Couldn't load %s module (%s)", HARDWARE_PROPERTIES_HARDWARE_MODULE_ID,
+ strerror(-err));
+ }
+}
+
+static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
+ if (gHardwarePropertiesModule && gHardwarePropertiesModule->getFanSpeeds) {
+ float *speeds = nullptr;
+ ssize_t size = gHardwarePropertiesModule->getFanSpeeds(gHardwarePropertiesModule, &speeds);
+
+ if (speeds && size > 0) {
+ jfloatArray fanSpeeds = env->NewFloatArray(size);
+ env->SetFloatArrayRegion(fanSpeeds, 0, size, speeds);
+ free(speeds);
+ return fanSpeeds;
+ }
+
+ if (size < 0) {
+ ALOGE("Cloudn't get fan speeds because of HAL error");
+ }
+ }
+ return env->NewFloatArray(0);
+}
+
+static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type) {
+ if (gHardwarePropertiesModule) {
+ ssize_t size = 0;
+ float *temps = nullptr;
+ switch (type) {
+ case DEVICE_TEMPERATURE_CPU:
+ if (gHardwarePropertiesModule->getCpuTemperatures) {
+ size = gHardwarePropertiesModule->getCpuTemperatures(gHardwarePropertiesModule,
+ &temps);
+ }
+ break;
+ case DEVICE_TEMPERATURE_GPU:
+ if (gHardwarePropertiesModule->getGpuTemperatures) {
+ size = gHardwarePropertiesModule->getGpuTemperatures(gHardwarePropertiesModule,
+ &temps);
+ }
+ break;
+ case DEVICE_TEMPERATURE_BATTERY:
+ if (gHardwarePropertiesModule->getBatteryTemperatures) {
+ size = gHardwarePropertiesModule->getBatteryTemperatures(gHardwarePropertiesModule,
+ &temps);
+ }
+ break;
+ }
+ if (temps && size > 0) {
+ jfloatArray deviceTemps = env->NewFloatArray(size);
+ env->SetFloatArrayRegion(deviceTemps, 0, size, temps);
+ free(temps);
+ return deviceTemps;
+ }
+ if (size < 0) {
+ ALOGE("Couldn't get device temperatures type=%d because of HAL error", type);
+ }
+ }
+ return env->NewFloatArray(0);
+}
+
+static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
+ if (gHardwarePropertiesModule && gHardwarePropertiesModule->getCpuUsages
+ && gCpuUsageInfoClassInfo.initMethod) {
+ int64_t *active_times = nullptr;
+ int64_t *total_times = nullptr;
+ ssize_t size = gHardwarePropertiesModule->getCpuUsages(gHardwarePropertiesModule,
+ &active_times, &total_times);
+ if (active_times && total_times && size > 0) {
+ jobjectArray cpuUsages = env->NewObjectArray(size, gCpuUsageInfoClassInfo.clazz,
+ nullptr);
+ for (ssize_t i = 0; i < size; ++i) {
+ jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
+ gCpuUsageInfoClassInfo.initMethod,
+ active_times[i], total_times[i]);
+ env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
+ }
+ free(active_times);
+ free(total_times);
+ return cpuUsages;
+ }
+
+ if (size < 0) {
+ ALOGE("Couldn't get CPU usages because of HAL error");
+ }
+ }
+ return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeInit", "()V",
+ (void*) nativeInit },
+ { "nativeGetFanSpeeds", "()[F",
+ (void*) nativeGetFanSpeeds },
+ { "nativeGetDeviceTemperatures", "(I)[F",
+ (void*) nativeGetDeviceTemperatures },
+ { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;",
+ (void*) nativeGetCpuUsages }
+};
+
+int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) {
+ gHardwarePropertiesModule = nullptr;
+ 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,
+ "<init>", "(JJ)V");
+ return res;
+}
+
+} /* namespace android */
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index ef5c56c..be99673 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -44,6 +44,7 @@
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 @@
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 0cf9328..511c1e7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -488,6 +488,7 @@
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 @@
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);