Merge "Use a separate hwcomposer hidl instance for vr flinger" into oc-mr1-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index d534830..2b2725f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1829,6 +1829,11 @@
result = unlink_if_exists(current_profile) && result;
result = unlink_if_exists(reference_profile) && result;
+ // We upgraded once the location of current profile for secondary dex files.
+ // Check for any previous left-overs and remove them as well.
+ std::string old_current_profile = dex_path + ".prof";
+ result = unlink_if_exists(old_current_profile);
+
// Try removing the directories as well, they might be empty.
result = rmdir_if_empty(oat_isa_dir) && result;
result = rmdir_if_empty(oat_dir) && result;
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index dab3236..46ed85f 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -38,16 +38,6 @@
#define TEST_PROFILE_DIR "/data/misc/profiles"
-#define REALLY_LONG_APP_NAME "com.example." \
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-
-#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
- "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
- "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
- "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
-
namespace android {
namespace installd {
@@ -88,6 +78,14 @@
virtual void TearDown() {
free(android_system_dirs.dirs);
}
+
+ std::string create_too_long_path(const std::string& seed) {
+ std::string result = seed;
+ for (size_t i = seed.size(); i < PKG_PATH_MAX; i++) {
+ result += "a";
+ }
+ return result;
+ }
};
TEST_F(UtilsTest, IsValidApkPath_BadPrefix) {
@@ -388,17 +386,18 @@
<< "Primary user package directory should be created correctly";
}
+
TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
char path[PKG_PATH_MAX];
-
- EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
+ std::string really_long_app_name = create_too_long_path("com.example");
+ EXPECT_EQ(-1, create_move_path(path, really_long_app_name.c_str(), "shared_prefs", 0))
<< "Should fail to create move path for primary user";
}
TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
char path[PKG_PATH_MAX];
-
- EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
+ std::string really_long_leaf_name = create_too_long_path("leaf_");
+ EXPECT_EQ(-1, create_move_path(path, "com.android.test", really_long_leaf_name.c_str(), 0))
<< "Should fail to create move path for primary user";
}
@@ -560,7 +559,7 @@
}
TEST_F(UtilsTest, CreateSecondaryCurrentProfile) {
- EXPECT_EQ("/data/user/0/com.example/secondary.dex.prof",
+ EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.cur.prof",
create_current_profile_path(/*user*/0,
"/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
}
@@ -571,5 +570,88 @@
"/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
}
+static void pass_secondary_dex_validation(const std::string& package_name,
+ const std::string& dex_path, int uid, int storage_flag) {
+ EXPECT_TRUE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+ storage_flag))
+ << dex_path << " should be allowed as a valid secondary dex path";
+}
+
+static void fail_secondary_dex_validation(const std::string& package_name,
+ const std::string& dex_path, int uid, int storage_flag) {
+ EXPECT_FALSE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+ storage_flag))
+ << dex_path << " should not be allowed as a valid secondary dex path";
+}
+
+TEST_F(UtilsTest, ValidateSecondaryDexFilesPath) {
+ std::string package_name = "com.test.app";
+ std::string app_dir_ce_user_0 = "/data/data/" + package_name;
+ std::string app_dir_ce_user_10 = "/data/user/10/" + package_name;
+
+ std::string app_dir_de_user_0 = "/data/user_de/0/" + package_name;
+ std::string app_dir_de_user_10 = "/data/user_de/10/" + package_name;
+
+ EXPECT_EQ(app_dir_ce_user_0,
+ create_data_user_ce_package_path(nullptr, 0, package_name.c_str()));
+ EXPECT_EQ(app_dir_ce_user_10,
+ create_data_user_ce_package_path(nullptr, 10, package_name.c_str()));
+
+ EXPECT_EQ(app_dir_de_user_0,
+ create_data_user_de_package_path(nullptr, 0, package_name.c_str()));
+ EXPECT_EQ(app_dir_de_user_10,
+ create_data_user_de_package_path(nullptr, 10, package_name.c_str()));
+
+ uid_t app_uid_for_user_0 = multiuser_get_uid(/*user_id*/0, /*app_id*/ 1234);
+ uid_t app_uid_for_user_10 = multiuser_get_uid(/*user_id*/10, /*app_id*/ 1234);
+
+ // Standard path for user 0 on CE storage.
+ pass_secondary_dex_validation(
+ package_name, app_dir_ce_user_0 + "/ce0.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+ // Standard path for user 10 on CE storage.
+ pass_secondary_dex_validation(
+ package_name, app_dir_ce_user_10 + "/ce10.dex", app_uid_for_user_10, FLAG_STORAGE_CE);
+
+ // Standard path for user 0 on DE storage.
+ pass_secondary_dex_validation(
+ package_name, app_dir_de_user_0 + "/de0.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+ // Standard path for user 10 on DE storage.
+ pass_secondary_dex_validation(
+ package_name, app_dir_de_user_10 + "/de0.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+ // Dex path for user 0 accessed from user 10.
+ fail_secondary_dex_validation(
+ package_name, app_dir_ce_user_0 + "/path0_from10.dex",
+ app_uid_for_user_10, FLAG_STORAGE_CE);
+
+ // Dex path for CE storage accessed with DE.
+ fail_secondary_dex_validation(
+ package_name, app_dir_ce_user_0 + "/ce_from_de.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+
+ // Dex path for DE storage accessed with CE.
+ fail_secondary_dex_validation(
+ package_name, app_dir_de_user_0 + "/de_from_ce.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+ // Location which does not start with '/'.
+ fail_secondary_dex_validation(
+ package_name, "without_slash.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+ // The dex file is not in the specified package directory.
+ fail_secondary_dex_validation(
+ "another.package", app_dir_ce_user_0 + "/for_another_package.dex",
+ app_uid_for_user_0, FLAG_STORAGE_DE);
+
+ // The dex path contains indirect directories.
+ fail_secondary_dex_validation(
+ package_name, app_dir_ce_user_0 + "/1/../foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+ fail_secondary_dex_validation(
+ package_name, app_dir_ce_user_0 + "/1/./foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+ // Super long path.
+ std::string too_long = create_too_long_path("too_long_");
+ fail_secondary_dex_validation(
+ package_name, app_dir_ce_user_10 + "/" + too_long, app_uid_for_user_10, FLAG_STORAGE_CE);
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 7c05417..0faddf0 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -238,13 +238,38 @@
// Keep profile paths in sync with ActivityThread and LoadedApk.
const std::string PROFILE_EXT = ".prof";
+const std::string CURRENT_PROFILE_EXT = ".cur";
const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
+// Gets the parent directory and the file name for the given secondary dex path.
+// Returns true on success, false on failure (if the dex_path does not have the expected
+// structure).
+static bool get_secondary_dex_location(const std::string& dex_path,
+ std::string* out_dir_name, std::string* out_file_name) {
+ size_t dirIndex = dex_path.rfind('/');
+ if (dirIndex == std::string::npos) {
+ return false;
+ }
+ if (dirIndex == dex_path.size() - 1) {
+ return false;
+ }
+ *out_dir_name = dex_path.substr(0, dirIndex);
+ *out_file_name = dex_path.substr(dirIndex + 1);
+
+ return true;
+}
+
std::string create_current_profile_path(userid_t user, const std::string& location,
bool is_secondary_dex) {
if (is_secondary_dex) {
- // Secondary dex profiles are stored next to the dex files using .prof extension.
- return StringPrintf("%s%s", location.c_str(), PROFILE_EXT.c_str());
+ // Secondary dex current profiles are stored next to the dex files under the oat folder.
+ std::string dex_dir;
+ std::string dex_name;
+ CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
+ << "Unexpected dir structure for secondary dex " << location;
+ return StringPrintf("%s/oat/%s%s%s",
+ dex_dir.c_str(), dex_name.c_str(), CURRENT_PROFILE_EXT.c_str(),
+ PROFILE_EXT.c_str());
} else {
// Profiles for primary apks are under /data/misc/profiles/cur.
std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
@@ -255,12 +280,10 @@
std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
if (is_secondary_dex) {
// Secondary dex reference profiles are stored next to the dex files under the oat folder.
- size_t dirIndex = location.rfind('/');
- CHECK(dirIndex != std::string::npos)
+ std::string dex_dir;
+ std::string dex_name;
+ CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
<< "Unexpected dir structure for secondary dex " << location;
-
- std::string dex_dir = location.substr(0, dirIndex);
- std::string dex_name = location.substr(dirIndex +1);
return StringPrintf("%s/oat/%s%s",
dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
} else {
@@ -781,21 +804,30 @@
const char* volume_uuid, int uid, int storage_flag) {
CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
+ // Empty paths are not allowed.
+ if (dex_path.empty()) { return false; }
+ // First character should always be '/'. No relative paths.
+ if (dex_path[0] != '/') { return false; }
+ // The last character should not be '/'.
+ if (dex_path[dex_path.size() - 1] == '/') { return false; }
+ // There should be no '.' after the directory marker.
+ if (dex_path.find("/.") != std::string::npos) { return false; }
+ // The path should be at most PKG_PATH_MAX long.
+ if (dex_path.size() > PKG_PATH_MAX) { return false; }
+
+ // The dex_path should be under the app data directory.
std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
? create_data_user_ce_package_path(
volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
: create_data_user_de_package_path(
volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
- dir_rec_t dir;
- if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) {
- LOG(WARNING) << "Could not get dir rec for " << app_private_dir;
+
+ if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
return false;
}
- // Usually secondary dex files have a nested directory structure.
- // Pick at most 10 subdirectories when validating (arbitrary value).
- // If the secondary dex file is >10 directory nested then validation will
- // fail and the file will not be compiled.
- return validate_path(&dir, dex_path.c_str(), /*max_subdirs*/ 10) == 0;
+
+ // If we got here we have a valid path.
+ return true;
}
/**
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 09fd0cb..83b8021 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -69,8 +69,13 @@
"TextOutput.cpp",
"IpPrefix.cpp",
"Value.cpp",
+ "aidl/android/content/pm/IPackageManagerNative.aidl",
],
+ aidl: {
+ export_aidl_headers: true,
+ },
+
cflags: [
"-Wall",
"-Wextra",
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
new file mode 100644
index 0000000..6b7254c
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 2017, 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.content.pm;
+
+/**
+ * Parallel implementation of certain {@link PackageManager} APIs that need to
+ * be exposed to native code.
+ * <p>These APIs are a parallel definition to the APIs in PackageManager, so,
+ * they can technically diverge. However, it's good practice to keep these
+ * APIs in sync with each other.
+ * <p>Because these APIs are exposed to native code, it's possible they will
+ * be exposed to privileged components [such as UID 0]. Care should be taken
+ * to avoid exposing potential security holes for methods where permission
+ * checks are bypassed based upon UID alone.
+ *
+ * @hide
+ */
+interface IPackageManagerNative {
+ /**
+ * Returns a set of names for the given UIDs.
+ * IMPORTANT: Unlike the Java version of this API, unknown UIDs are
+ * not represented by 'null's. Instead, they are represented by empty
+ * strings.
+ */
+ @utf8InCpp String[] getNamesForUids(in int[] uids);
+}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4558fe8..3996305 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -20,6 +20,9 @@
cc_library_shared {
name: "libgui",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
clang: true,
cppflags: [
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 6630d90..cabe94e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -15,6 +15,9 @@
cc_library_shared {
name: "libui",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
clang: true,
cppflags: [
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index b4cc211..1cfc513 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -117,6 +117,9 @@
cc_library_shared {
name: "libEGL",
defaults: ["egl_libs_defaults"],
+ vndk: {
+ enabled: true,
+ },
srcs: [
"EGL/egl_tls.cpp",
"EGL/egl_cache.cpp",
@@ -180,6 +183,9 @@
cc_library_shared {
name: "libGLESv2",
defaults: ["gles_libs_defaults"],
+ vndk: {
+ enabled: true,
+ },
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv2\""],
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ba0af5f..4623be7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4398,7 +4398,7 @@
bool secureLayerIsVisible = false;
for (const auto& layer : mDrawingState.layersSortedByZ) {
const Layer::State& state(layer->getDrawingState());
- if (layer->belongsToDisplay(hw->getLayerStack(), false) ||
+ if (!layer->belongsToDisplay(hw->getLayerStack(), false) ||
(state.z < minLayerZ || state.z > maxLayerZ)) {
continue;
}
diff --git a/services/thermalservice/Android.bp b/services/thermalservice/Android.bp
new file mode 100644
index 0000000..d754560
--- /dev/null
+++ b/services/thermalservice/Android.bp
@@ -0,0 +1,61 @@
+subdirs = [
+ "libthermalcallback"
+]
+
+cc_library {
+ name: "libthermalservice",
+
+ srcs: [
+ "aidl/android/os/IThermalEventListener.aidl",
+ "aidl/android/os/IThermalService.aidl",
+ "aidl/android/os/Temperature.cpp",
+ ],
+ aidl: {
+ include_dirs: ["frameworks/native/services/thermalservice/aidl"],
+ export_aidl_headers: true,
+ },
+ export_include_dirs: ["aidl"],
+
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+}
+
+cc_binary {
+ name: "thermalserviced",
+
+ srcs: [
+ "ThermalService.cpp",
+ "thermalserviced.cpp",
+ ],
+
+ include_dirs: ["frameworks/native"],
+
+ shared_libs: [
+ "libthermalservice",
+ "libbinder",
+ "libutils",
+ "libthermalcallback",
+ "android.hardware.thermal@1.1",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+
+ init_rc: ["thermalservice.rc"],
+}
diff --git a/services/thermalservice/ThermalService.cpp b/services/thermalservice/ThermalService.cpp
new file mode 100644
index 0000000..6e09a83
--- /dev/null
+++ b/services/thermalservice/ThermalService.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "ThermalService.h"
+#include <android/os/IThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace os {
+
+/**
+ * Notify registered listeners of a thermal throttling start/stop event.
+ * @param temperature the temperature at which the event was generated
+ */
+binder::Status ThermalService::notifyThrottling(
+ const bool isThrottling, const Temperature& temperature) {
+ Mutex::Autolock _l(mListenersLock);
+
+ mThrottled = isThrottling;
+ mThrottleTemperature = temperature;
+
+ for (size_t i = 0; i < mListeners.size(); i++) {
+ mListeners[i]->notifyThrottling(isThrottling, temperature);
+ }
+ return binder::Status::ok();
+}
+
+/**
+ * Query whether the system is currently thermal throttling.
+ * @return true if currently thermal throttling, else false
+ */
+binder::Status ThermalService::isThrottling(bool* _aidl_return) {
+ Mutex::Autolock _l(mListenersLock);
+ *_aidl_return = mThrottled;
+ return binder::Status::ok();
+}
+
+/**
+ * Register a new thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ * notifications are to be sent
+ */
+binder::Status ThermalService::registerThermalEventListener(
+ const sp<IThermalEventListener>& listener) {
+ {
+ if (listener == NULL)
+ return binder::Status::ok();
+ Mutex::Autolock _l(mListenersLock);
+ // check whether this is a duplicate
+ for (size_t i = 0; i < mListeners.size(); i++) {
+ if (IInterface::asBinder(mListeners[i]) ==
+ IInterface::asBinder(listener)) {
+ return binder::Status::ok();
+ }
+ }
+
+ mListeners.add(listener);
+ IInterface::asBinder(listener)->linkToDeath(this);
+ }
+
+ return binder::Status::ok();
+}
+
+/**
+ * Unregister a previously-registered thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ * notifications are to no longer be sent
+ */
+binder::Status ThermalService::unregisterThermalEventListener(
+ const sp<IThermalEventListener>& listener) {
+ if (listener == NULL)
+ return binder::Status::ok();
+ Mutex::Autolock _l(mListenersLock);
+ for (size_t i = 0; i < mListeners.size(); i++) {
+ if (IInterface::asBinder(mListeners[i]) ==
+ IInterface::asBinder(listener)) {
+ IInterface::asBinder(mListeners[i])->unlinkToDeath(this);
+ mListeners.removeAt(i);
+ break;
+ }
+ }
+
+ return binder::Status::ok();
+}
+
+void ThermalService::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock _l(mListenersLock);
+
+ for (size_t i = 0; i < mListeners.size(); i++) {
+ if (IInterface::asBinder(mListeners[i]) == who) {
+ mListeners.removeAt(i);
+ break;
+ }
+ }
+}
+
+/**
+ * Publish the supplied ThermalService to servicemanager.
+ */
+void ThermalService::publish(
+ const sp<ThermalService>& service) {
+ defaultServiceManager()->addService(String16("thermalservice"),
+ service);
+}
+
+} // namespace os
+} // namespace android
diff --git a/services/thermalservice/ThermalService.h b/services/thermalservice/ThermalService.h
new file mode 100644
index 0000000..17dfcbc
--- /dev/null
+++ b/services/thermalservice/ThermalService.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICE_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICE_H
+
+#include <android/os/BnThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace os {
+
+class ThermalService : public BnThermalService,
+ public IBinder::DeathRecipient {
+public:
+ ThermalService() : mThrottled(false) {};
+ void publish(const sp<ThermalService>& service);
+ binder::Status notifyThrottling(
+ const bool isThrottling, const Temperature& temperature);
+
+private:
+ Mutex mListenersLock;
+ Vector<sp<IThermalEventListener> > mListeners;
+ bool mThrottled;
+ Temperature mThrottleTemperature;
+
+ binder::Status registerThermalEventListener(
+ const sp<IThermalEventListener>& listener);
+ binder::Status unregisterThermalEventListener(
+ const sp<IThermalEventListener>& listener);
+ binder::Status isThrottling(bool* _aidl_return);
+ void binderDied(const wp<IBinder>& who);
+};
+
+}; // namespace os
+}; // namespace android
+
+#endif // ANDROID_THERMALSERVICE_THERMALSERVICE_H
diff --git a/services/thermalservice/aidl/android/os/IThermalEventListener.aidl b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
new file mode 100644
index 0000000..050325e
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2017, 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.Temperature;
+
+/**
+ * Listener for thermal events.
+ * {@hide}
+ */
+oneway interface IThermalEventListener {
+ /**
+ * Called when a thermal throttling start/stop event is received.
+ * @param temperature the temperature at which the event was generated.
+ */
+ void notifyThrottling(
+ in boolean isThrottling, in Temperature temperature);
+}
diff --git a/services/thermalservice/aidl/android/os/IThermalService.aidl b/services/thermalservice/aidl/android/os/IThermalService.aidl
new file mode 100644
index 0000000..e699202
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalService.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2017, 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.IThermalEventListener;
+import android.os.Temperature;
+
+/** {@hide} */
+interface IThermalService {
+ /**
+ * Register a listener for thermal events.
+ * @param listener the IThermalEventListener to be notified.
+ * {@hide}
+ */
+ void registerThermalEventListener(in IThermalEventListener listener);
+ /**
+ * Unregister a previously-registered listener for thermal events.
+ * @param listener the IThermalEventListener to no longer be notified.
+ * {@hide}
+ */
+ void unregisterThermalEventListener(in IThermalEventListener listener);
+ /**
+ * Send a thermal throttling start/stop notification to all listeners.
+ * @param temperature the temperature at which the event was generated.
+ * {@hide}
+ */
+ oneway void notifyThrottling(
+ in boolean isThrottling, in Temperature temperature);
+ /**
+ * Return whether system performance is currently thermal throttling.
+ * {@hide}
+ */
+ boolean isThrottling();
+}
diff --git a/services/thermalservice/aidl/android/os/Temperature.aidl b/services/thermalservice/aidl/android/os/Temperature.aidl
new file mode 100644
index 0000000..0293c39
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.aidl
@@ -0,0 +1,5 @@
+package android.os;
+
+/* Encodes a temperature used by ThermalService. */
+
+parcelable Temperature cpp_header "android/os/Temperature.h";
diff --git a/services/thermalservice/aidl/android/os/Temperature.cpp b/services/thermalservice/aidl/android/os/Temperature.cpp
new file mode 100644
index 0000000..df207b7
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "android/os/Temperature.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <binder/Parcel.h>
+#include <hardware/thermal.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+namespace android {
+namespace os {
+
+Temperature::Temperature() : value_(NAN), type_(DEVICE_TEMPERATURE_UNKNOWN) {}
+
+Temperature::Temperature(const float value, const int type) :
+ value_(value), type_(type) {}
+
+Temperature::~Temperature() {}
+
+/*
+ * Parcel read/write code must be kept in sync with
+ * frameworks/base/core/java/android/os/Temperature.java
+ */
+
+status_t Temperature::readFromParcel(const Parcel* p) {
+ value_ = p->readFloat();
+ type_ = p->readInt32();
+ return OK;
+}
+
+status_t Temperature::writeToParcel(Parcel* p) const {
+ p->writeFloat(value_);
+ p->writeInt32(type_);
+ return OK;
+}
+
+} // namespace os
+} // namespace android
diff --git a/services/thermalservice/aidl/android/os/Temperature.h b/services/thermalservice/aidl/android/os/Temperature.h
new file mode 100644
index 0000000..bbc5607
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.h
@@ -0,0 +1,33 @@
+#ifndef ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+#define ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+class Temperature : public Parcelable {
+ public:
+
+ Temperature();
+ Temperature(const float value, const int type);
+ ~Temperature() override;
+
+ float getValue() const {return value_;};
+ float getType() const {return type_;};
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ // The value of the temperature as a float, or NAN if unknown.
+ float value_;
+ // The type of the temperature, an enum temperature_type from
+ // hardware/thermal.h
+ int type_;
+};
+
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
diff --git a/services/thermalservice/libthermalcallback/Android.bp b/services/thermalservice/libthermalcallback/Android.bp
new file mode 100644
index 0000000..e98506e
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/Android.bp
@@ -0,0 +1,19 @@
+cc_library_shared {
+ name: "libthermalcallback",
+ srcs: [
+ "ThermalCallback.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ include_dirs: ["frameworks/native"],
+ shared_libs: [
+ "android.hardware.thermal@1.1",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libthermalservice",
+ "libutils",
+ ],
+}
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.cpp b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
new file mode 100644
index 0000000..5e094fa
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
@@ -0,0 +1,69 @@
+#define LOG_TAG "android.hardware.thermal.thermalcallback@1.1-impl"
+#include <log/log.h>
+
+#include "ThermalCallback.h"
+#include "services/thermalservice/ThermalService.h"
+#include <math.h>
+#include <android/os/Temperature.h>
+#include <hardware/thermal.h>
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::os::ThermalService;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+
+// Register a binder ThermalService object for sending events
+void ThermalCallback::registerThermalService(sp<ThermalService> thermalService)
+{
+ mThermalService = thermalService;
+}
+
+// Methods from IThermalCallback::V1_1 follow.
+Return<void> ThermalCallback::notifyThrottling(
+ bool isThrottling,
+ const android::hardware::thermal::V1_0::Temperature& temperature) {
+
+ // Convert HIDL IThermal Temperature to binder IThermalService Temperature.
+ if (mThermalService != nullptr) {
+ float value = NAN;
+ int type = DEVICE_TEMPERATURE_UNKNOWN;
+
+ switch(temperature.type) {
+ case TemperatureType::CPU:
+ type = DEVICE_TEMPERATURE_CPU;
+ break;
+ case TemperatureType::GPU:
+ type = DEVICE_TEMPERATURE_GPU;
+ break;
+ case TemperatureType::BATTERY:
+ type = DEVICE_TEMPERATURE_BATTERY;
+ break;
+ case TemperatureType::SKIN:
+ type = DEVICE_TEMPERATURE_SKIN;
+ break;
+ case TemperatureType::UNKNOWN:
+ default:
+ type = DEVICE_TEMPERATURE_UNKNOWN;
+ break;
+ }
+
+ value = temperature.currentValue == UNKNOWN_TEMPERATURE ? NAN :
+ temperature.currentValue;
+
+ android::os::Temperature thermal_svc_temp(value, type);
+ mThermalService->notifyThrottling(isThrottling, thermal_svc_temp);
+ } else {
+ ALOGE("IThermalService binder service not created, drop throttling event");
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace thermal
+} // namespace hardware
+} // namespace android
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.h b/services/thermalservice/libthermalcallback/ThermalCallback.h
new file mode 100644
index 0000000..3d72c68
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.h
@@ -0,0 +1,43 @@
+#ifndef ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+#define ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+#include <android/os/Temperature.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "services/thermalservice/ThermalService.h"
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::os::ThermalService;
+
+class ThermalCallback : public IThermalCallback {
+ public:
+ // Register a binder ThermalService object for sending events
+ void registerThermalService(sp<ThermalService> thermalService);
+
+ // Methods from IThermalCallback::V1_1 follow.
+ Return<void> notifyThrottling(
+ bool isThrottling,
+ const android::hardware::thermal::V1_0::Temperature& temperature)
+ override;
+
+ private:
+ // Our registered binder ThermalService object to use for sending events
+ sp<android::os::ThermalService> mThermalService;
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace thermal
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
diff --git a/services/thermalservice/thermalservice.rc b/services/thermalservice/thermalservice.rc
new file mode 100644
index 0000000..b9836ce
--- /dev/null
+++ b/services/thermalservice/thermalservice.rc
@@ -0,0 +1,2 @@
+service thermalservice /system/bin/thermalserviced
+ class core
diff --git a/services/thermalservice/thermalserviced.cpp b/services/thermalservice/thermalserviced.cpp
new file mode 100644
index 0000000..b9315b8
--- /dev/null
+++ b/services/thermalservice/thermalserviced.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2017 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 "thermalserviced"
+#include <log/log.h>
+
+#include "thermalserviced.h"
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+#include <android/hardware/thermal/1.1/IThermal.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
+
+using namespace android;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::os::ThermalService;
+
+template<typename T>
+using Return = hardware::Return<T>;
+
+namespace {
+
+// Our thermalserviced main object
+ThermalServiceDaemon* gThermalServiceDaemon;
+
+// Thermal HAL client
+sp<IThermal> gThermalHal = nullptr;
+
+// Binder death notifier informing of Thermal HAL death.
+struct ThermalServiceDeathRecipient : hidl_death_recipient {
+ virtual void serviceDied(
+ uint64_t cookie __unused, const wp<IBase>& who __unused) {
+ gThermalHal = nullptr;
+ ALOGE("IThermal HAL died");
+ gThermalServiceDaemon->getThermalHal();
+ }
+};
+
+sp<ThermalServiceDeathRecipient> gThermalHalDied = nullptr;
+
+} // anonymous namespace
+
+void ThermalServiceDaemon::thermalServiceStartup() {
+ // Binder IThermalService startup
+ mThermalService = new android::os::ThermalService;
+ mThermalService->publish(mThermalService);
+ // Register IThermalService object with IThermalCallback
+ if (mThermalCallback != nullptr)
+ mThermalCallback->registerThermalService(mThermalService);
+ IPCThreadState::self()->joinThreadPool();
+}
+
+// Lookup Thermal HAL, register death notifier, register our
+// ThermalCallback with the Thermal HAL.
+void ThermalServiceDaemon::getThermalHal() {
+ gThermalHal = IThermal::getService();
+ if (gThermalHal == nullptr) {
+ ALOGW("Unable to get Thermal HAL V1.1, vendor thermal event notification not available");
+ return;
+ }
+
+ // Binder death notifier for Thermal HAL
+ if (gThermalHalDied == nullptr)
+ gThermalHalDied = new ThermalServiceDeathRecipient();
+
+ if (gThermalHalDied != nullptr)
+ gThermalHal->linkToDeath(gThermalHalDied, 0x451F /* cookie */);
+
+ if (mThermalCallback != nullptr) {
+ Return<void> ret = gThermalHal->registerThermalCallback(
+ mThermalCallback);
+ if (!ret.isOk())
+ ALOGE("registerThermalCallback failed, status: %s",
+ ret.description().c_str());
+ }
+}
+
+void ThermalServiceDaemon::thermalCallbackStartup() {
+ status_t err;
+
+ // HIDL IThermalCallback startup
+ // Need at least 2 threads in thread pool since we wait for dead HAL
+ // to come back on the binder death notification thread and we need
+ // another thread for the incoming service now available call.
+ configureRpcThreadpool(2, false /* callerWillJoin */);
+ mThermalCallback = new ThermalCallback();
+ err = mThermalCallback->registerAsService();
+ ALOGE_IF(err != OK, "Cannot register %s: %d",
+ IThermalCallback::descriptor, err);
+
+ // Lookup Thermal HAL and register our ThermalCallback.
+ getThermalHal();
+}
+
+int main(int /*argc*/, char** /*argv*/) {
+ gThermalServiceDaemon = new ThermalServiceDaemon();
+ gThermalServiceDaemon->thermalCallbackStartup();
+ gThermalServiceDaemon->thermalServiceStartup();
+ /* NOTREACHED */
+}
diff --git a/services/thermalservice/thermalserviced.h b/services/thermalservice/thermalserviced.h
new file mode 100644
index 0000000..309e2fe
--- /dev/null
+++ b/services/thermalservice/thermalserviced.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICED_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICED_H
+
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+using namespace android;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::os::ThermalService;
+
+class ThermalServiceDaemon {
+ public:
+ void thermalServiceStartup();
+ void thermalCallbackStartup();
+ void getThermalHal();
+ ThermalServiceDaemon() {};
+
+ private:
+ sp<ThermalService> mThermalService;
+ sp<ThermalCallback> mThermalCallback;
+};
+
+#endif // ANDROID_THERMALSERVICE_THERMALSERVICED_H