Merge "VR: Replace sw sync fences with egl sync fences"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index e33f099..349bbed 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1336,22 +1336,14 @@
return std::string(hash_buffer);
}
-static void SendShellBroadcast(const std::string& action, const std::vector<std::string>& args) {
- std::vector<std::string> am = {
- "/system/bin/cmd", "activity", "broadcast", "--user", "0", "-a", action};
+static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
+ // clang-format off
+ std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
+ "--receiver-foreground", "--receiver-include-background", "-a", action};
+ // clang-format on
am.insert(am.end(), args.begin(), args.end());
- // TODO: explicity setting Shell's component to allow broadcast to launch it.
- // That might break other components that are listening to the bugreport notifications
- // (com.android.internal.intent.action.BUGREPORT_STARTED and
- // com.android.internal.intent.action.BUGREPORT_STOPED), but
- // those should be just handled by Shell anyways.
- // A more generic alternative would be passing the -f 0x01000000 flag (or whatever
- // value is defined by FLAG_RECEIVER_INCLUDE_BACKGROUND), but that would reset the
- // --receiver-foreground option
- am.push_back("com.android.shell");
-
RunCommand("", am,
CommandOptions::WithTimeout(20)
.Log("Sending broadcast: '%s'\n")
@@ -1594,14 +1586,14 @@
// clang-format off
std::vector<std::string> am_args = {
- "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
+ "--receiver-permission", "android.permission.DUMP",
"--es", "android.intent.extra.NAME", ds.name_,
"--ei", "android.intent.extra.ID", std::to_string(ds.id_),
"--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
"--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
};
// clang-format on
- SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
+ SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
}
if (use_control_socket) {
dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
@@ -1809,7 +1801,7 @@
// clang-format off
std::vector<std::string> am_args = {
- "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
+ "--receiver-permission", "android.permission.DUMP",
"--ei", "android.intent.extra.ID", std::to_string(ds.id_),
"--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
"--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
@@ -1826,10 +1818,10 @@
am_args.push_back("--es");
am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
am_args.push_back(SHA256_file_hash(ds.path_));
- SendShellBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
- am_args);
+ SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
+ am_args);
} else {
- SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
+ SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
}
} else {
MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index d1bdded..6caf149 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -16,8 +16,9 @@
#include "CacheItem.h"
-#include <stdint.h>
#include <inttypes.h>
+#include <stdint.h>
+#include <sys/xattr.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
@@ -29,12 +30,23 @@
namespace android {
namespace installd {
-CacheItem::CacheItem(const std::shared_ptr<CacheItem>& parent, FTSENT* p) : mParent(parent) {
+CacheItem::CacheItem(FTSENT* p) {
level = p->fts_level;
directory = S_ISDIR(p->fts_statp->st_mode);
size = p->fts_statp->st_blocks * 512;
modified = p->fts_statp->st_mtime;
- mName = p->fts_path;
+
+ mParent = static_cast<CacheItem*>(p->fts_parent->fts_pointer);
+ if (mParent) {
+ atomic = mParent->atomic;
+ tombstone = mParent->tombstone;
+ mName = p->fts_name;
+ mName.insert(0, "/");
+ } else {
+ atomic = false;
+ tombstone = false;
+ mName = p->fts_path;
+ }
}
CacheItem::~CacheItem() {
@@ -46,7 +58,7 @@
std::string CacheItem::buildPath() {
std::string res = mName;
- std::shared_ptr<CacheItem> parent = mParent;
+ CacheItem* parent = mParent;
while (parent) {
res.insert(0, parent->mName);
parent = parent->mParent;
@@ -57,13 +69,47 @@
int CacheItem::purge() {
auto path = buildPath();
if (directory) {
- return delete_dir_contents_and_dir(path, true);
- } else {
- int res = unlink(path.c_str());
- if (res != 0) {
- PLOG(WARNING) << "Failed to unlink " << path;
+ FTS *fts;
+ FTSENT *p;
+ char *argv[] = { (char*) path.c_str(), nullptr };
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ PLOG(WARNING) << "Failed to fts_open " << path;
+ return -1;
}
- return res;
+ while ((p = fts_read(fts)) != nullptr) {
+ switch (p->fts_info) {
+ case FTS_D:
+ if (p->fts_level == 0) {
+ p->fts_number = tombstone;
+ } else {
+ p->fts_number = p->fts_parent->fts_number
+ | (getxattr(p->fts_path, kXattrCacheTombstone, nullptr, 0) >= 0);
+ }
+ break;
+ case FTS_F:
+ if (p->fts_parent->fts_number) {
+ truncate(p->fts_path, 0);
+ } else {
+ unlink(p->fts_path);
+ }
+ break;
+ case FTS_DEFAULT:
+ case FTS_SL:
+ case FTS_SLNONE:
+ unlink(p->fts_path);
+ break;
+ case FTS_DP:
+ rmdir(p->fts_path);
+ break;
+ }
+ }
+ return 0;
+ } else {
+ if (tombstone) {
+ return truncate(path.c_str(), 0);
+ } else {
+ return unlink(path.c_str());
+ }
}
}
diff --git a/cmds/installd/CacheItem.h b/cmds/installd/CacheItem.h
index bec8bc8..afbb15d 100644
--- a/cmds/installd/CacheItem.h
+++ b/cmds/installd/CacheItem.h
@@ -36,7 +36,7 @@
*/
class CacheItem {
public:
- CacheItem(const std::shared_ptr<CacheItem>& parent, FTSENT* p);
+ CacheItem(FTSENT* p);
~CacheItem();
std::string toString();
@@ -46,11 +46,13 @@
short level;
bool directory;
+ bool atomic;
+ bool tombstone;
int64_t size;
time_t modified;
private:
- std::shared_ptr<CacheItem> mParent;
+ CacheItem* mParent;
std::string mName;
DISALLOW_COPY_AND_ASSIGN(CacheItem);
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 23c4330..9377836 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -20,6 +20,7 @@
#include <fts.h>
#include <sys/quota.h>
+#include <sys/xattr.h>
#include <utils/Trace.h>
#include <android-base/logging.h>
@@ -86,30 +87,59 @@
PLOG(WARNING) << "Failed to fts_open " << path;
return;
}
- // TODO: add support for "user.atomic" and "user.tombstone" xattrs
- while ((p = fts_read(fts)) != NULL) {
+ while ((p = fts_read(fts)) != nullptr) {
+ if (p->fts_level == 0) continue;
+
+ // Create tracking nodes for everything we encounter
switch (p->fts_info) {
case FTS_D:
- // Track the newest mtime of anything inside so we consider
- // deleting the directory last
- p->fts_number = p->fts_statp->st_mtime;
- break;
- case FTS_DP:
- p->fts_statp->st_mtime = p->fts_number;
-
- // Ignore the actual top-level cache directories
- if (p->fts_level == 0) break;
case FTS_DEFAULT:
case FTS_F:
case FTS_SL:
- case FTS_SLNONE:
- // TODO: optimize path memory footprint
- items.push_back(std::shared_ptr<CacheItem>(new CacheItem(nullptr, p)));
+ case FTS_SLNONE: {
+ auto item = std::shared_ptr<CacheItem>(new CacheItem(p));
+ p->fts_pointer = static_cast<void*>(item.get());
+ items.push_back(item);
+ }
+ }
- // Track the newest modified item under this tree
- p->fts_parent->fts_number =
- std::max(p->fts_parent->fts_number, p->fts_statp->st_mtime);
- break;
+ switch (p->fts_info) {
+ case FTS_D: {
+ auto item = static_cast<CacheItem*>(p->fts_pointer);
+ item->atomic |= (getxattr(p->fts_path, kXattrCacheAtomic, nullptr, 0) >= 0);
+ item->tombstone |= (getxattr(p->fts_path, kXattrCacheTombstone, nullptr, 0) >= 0);
+
+ // When atomic, immediately collect all files under tree
+ if (item->atomic) {
+ while ((p = fts_read(fts)) != nullptr) {
+ if (p->fts_info == FTS_DP && p->fts_level == item->level) break;
+ switch (p->fts_info) {
+ case FTS_D:
+ case FTS_DEFAULT:
+ case FTS_F:
+ case FTS_SL:
+ case FTS_SLNONE:
+ item->size += p->fts_statp->st_blocks * 512;
+ item->modified = std::max(item->modified, p->fts_statp->st_mtime);
+ }
+ }
+ }
+ }
+ }
+
+ // Bubble up modified time to parent
+ switch (p->fts_info) {
+ case FTS_DP:
+ case FTS_DEFAULT:
+ case FTS_F:
+ case FTS_SL:
+ case FTS_SLNONE: {
+ auto item = static_cast<CacheItem*>(p->fts_pointer);
+ auto parent = static_cast<CacheItem*>(p->fts_parent->fts_pointer);
+ if (parent) {
+ parent->modified = std::max(parent->modified, item->modified);
+ }
+ }
}
}
fts_close(fts);
@@ -137,7 +167,7 @@
}
return left->directory;
};
- std::sort(items.begin(), items.end(), cmp);
+ std::stable_sort(items.begin(), items.end(), cmp);
ATRACE_END();
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 535d060..a84b051 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -86,7 +86,8 @@
static constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
static constexpr int FLAG_USE_QUOTA = 1 << 12;
static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
-static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 14;
+static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
+static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15;
namespace {
@@ -833,6 +834,14 @@
ATRACE_BEGIN("bounce");
std::shared_ptr<CacheTracker> active;
while (active || !queue.empty()) {
+ // Only look at apps under quota when explicitly requested
+ if (active && (active->getCacheRatio() < 10000)
+ && !(flags & FLAG_FREE_CACHE_V2_DEFY_QUOTA)) {
+ LOG(DEBUG) << "Active ratio " << active->getCacheRatio()
+ << " isn't over quota, and defy not requested";
+ break;
+ }
+
// Find the best tracker to work with; this might involve swapping
// if the active tracker is no longer the most over quota
bool nextBetter = active && !queue.empty()
@@ -2014,5 +2023,11 @@
return mQuotaDevices[path];
}
+binder::Status InstalldNativeService::isQuotaSupported(
+ const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) {
+ *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty();
+ return ok();
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index b3dbaf4..feb2219 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -111,6 +111,8 @@
const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
binder::Status invalidateMounts();
+ binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
+ bool* _aidl_return);
private:
std::recursive_mutex mLock;
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index b45df87..4195a01 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -77,4 +77,5 @@
int storage_flag);
void invalidateMounts();
+ boolean isQuotaSupported(@nullable @utf8InCpp String uuid);
}
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index a32df22..b5b080d 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -14,3 +14,22 @@
"libdiskusage",
],
}
+
+cc_test {
+ name: "installd_cache_test",
+ clang: true,
+ srcs: ["installd_cache_test.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "liblogwrap",
+ "libselinux",
+ "libutils",
+ ],
+ static_libs: [
+ "libinstalld",
+ "libdiskusage",
+ ],
+}
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
new file mode 100644
index 0000000..50a47d2
--- /dev/null
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -0,0 +1,323 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <sys/statvfs.h>
+#include <sys/xattr.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+
+#include "InstalldNativeService.h"
+#include "globals.h"
+#include "utils.h"
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+constexpr const char* kTestUuid = "TEST";
+
+constexpr int64_t kKbInBytes = 1024;
+constexpr int64_t kMbInBytes = 1024 * kKbInBytes;
+constexpr int64_t kGbInBytes = 1024 * kMbInBytes;
+constexpr int64_t kTbInBytes = 1024 * kGbInBytes;
+
+static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
+static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
+
+int get_property(const char *key, char *value, const char *default_value) {
+ return property_get(key, value, default_value);
+}
+
+bool calculate_oat_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *oat_dir ATTRIBUTE_UNUSED,
+ const char *apk_path ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+bool calculate_odex_file_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *apk_path ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX] ATTRIBUTE_UNUSED,
+ const char *src ATTRIBUTE_UNUSED,
+ const char *instruction_set ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+static void mkdir(const char* path) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ ::mkdir(fullPath, 0755);
+}
+
+static void touch(const char* path, int len, int time) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ int fd = ::open(fullPath, O_RDWR | O_CREAT, 0644);
+ ::fallocate(fd, 0, 0, len);
+ ::close(fd);
+ struct utimbuf times;
+ times.actime = times.modtime = std::time(0) + time;
+ ::utime(fullPath, ×);
+}
+
+static int exists(const char* path) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ return ::access(fullPath, F_OK);
+}
+
+static int64_t size(const char* path) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ struct stat buf;
+ if (!stat(fullPath, &buf)) {
+ return buf.st_size;
+ } else {
+ return -1;
+ }
+}
+
+static int64_t free() {
+ struct statvfs buf;
+ if (!statvfs("/data/local/tmp", &buf)) {
+ return buf.f_bavail * buf.f_bsize;
+ } else {
+ return -1;
+ }
+}
+
+static void setxattr(const char* path, const char* key) {
+ const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
+ ::setxattr(fullPath, key, "", 0, 0);
+}
+
+class CacheTest : public testing::Test {
+protected:
+ InstalldNativeService* service;
+ std::unique_ptr<std::string> testUuid;
+
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
+
+ service = new InstalldNativeService();
+ testUuid = std::make_unique<std::string>();
+ *testUuid = std::string(kTestUuid);
+ system("mkdir -p /data/local/tmp/user/0");
+ }
+
+ virtual void TearDown() {
+ delete service;
+ system("rm -rf /data/local/tmp/user");
+ }
+};
+
+TEST_F(CacheTest, FreeCache_All) {
+ mkdir("com.example");
+ touch("com.example/normal", 1 * kMbInBytes, 60);
+ mkdir("com.example/cache");
+ mkdir("com.example/cache/foo");
+ touch("com.example/cache/foo/one", 1 * kMbInBytes, 60);
+ touch("com.example/cache/foo/two", 2 * kMbInBytes, 120);
+
+ EXPECT_EQ(0, exists("com.example/normal"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/two"));
+
+ service->freeCache(testUuid, kTbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(0, exists("com.example/normal"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/two"));
+}
+
+TEST_F(CacheTest, FreeCache_Age) {
+ mkdir("com.example");
+ mkdir("com.example/cache");
+ mkdir("com.example/cache/foo");
+ touch("com.example/cache/foo/one", kMbInBytes, 60);
+ touch("com.example/cache/foo/two", kMbInBytes, 120);
+
+ service->freeCache(testUuid, free() + kKbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/two"));
+
+ service->freeCache(testUuid, free() + kKbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/two"));
+}
+
+TEST_F(CacheTest, FreeCache_Tombstone) {
+ mkdir("com.example");
+ mkdir("com.example/cache");
+ mkdir("com.example/cache/foo");
+ touch("com.example/cache/foo/foo1", 1 * kMbInBytes, 60);
+ touch("com.example/cache/foo/foo2", 1 * kMbInBytes, 60);
+ mkdir("com.example/cache/bar");
+ touch("com.example/cache/bar/bar1", 2 * kMbInBytes, 120);
+ touch("com.example/cache/bar/bar2", 2 * kMbInBytes, 120);
+
+ setxattr("com.example/cache/bar", "user.cache_tombstone");
+
+ EXPECT_EQ(0, exists("com.example/cache/foo/foo1"));
+ EXPECT_EQ(0, exists("com.example/cache/foo/foo2"));
+ EXPECT_EQ(0, exists("com.example/cache/bar/bar1"));
+ EXPECT_EQ(0, exists("com.example/cache/bar/bar2"));
+ EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1"));
+ EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2"));
+
+ service->freeCache(testUuid, kTbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/foo2"));
+ EXPECT_EQ(0, exists("com.example/cache/bar/bar1"));
+ EXPECT_EQ(0, exists("com.example/cache/bar/bar2"));
+ EXPECT_EQ(0, size("com.example/cache/bar/bar1"));
+ EXPECT_EQ(0, size("com.example/cache/bar/bar2"));
+}
+
+TEST_F(CacheTest, FreeCache_Atomic) {
+ mkdir("com.example");
+ mkdir("com.example/cache");
+ mkdir("com.example/cache/foo");
+ touch("com.example/cache/foo/foo1", 1 * kMbInBytes, 60);
+ touch("com.example/cache/foo/foo2", 1 * kMbInBytes, 120);
+
+ setxattr("com.example/cache/foo", "user.cache_atomic");
+
+ service->freeCache(testUuid, free() + kKbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
+ EXPECT_EQ(-1, exists("com.example/cache/foo/foo2"));
+}
+
+TEST_F(CacheTest, FreeCache_AtomicTombstone) {
+ LOG(INFO) << "FreeCache_AtomicTombstone";
+
+ mkdir("com.example");
+ mkdir("com.example/cache");
+
+ // this dir must look really old for some reason?
+ mkdir("com.example/cache/atomic");
+ touch("com.example/cache/atomic/file1", kMbInBytes, 120);
+ touch("com.example/cache/atomic/file2", kMbInBytes, 120);
+ mkdir("com.example/cache/atomic/dir");
+ touch("com.example/cache/atomic/dir/file1", kMbInBytes, 120);
+ touch("com.example/cache/atomic/dir/file2", kMbInBytes, 120);
+ mkdir("com.example/cache/atomic/tomb");
+ touch("com.example/cache/atomic/tomb/file1", kMbInBytes, 120);
+ touch("com.example/cache/atomic/tomb/file2", kMbInBytes, 120);
+ mkdir("com.example/cache/atomic/tomb/dir");
+ touch("com.example/cache/atomic/tomb/dir/file1", kMbInBytes, 120);
+ touch("com.example/cache/atomic/tomb/dir/file2", kMbInBytes, 120);
+
+ mkdir("com.example/cache/tomb");
+ touch("com.example/cache/tomb/file1", kMbInBytes, 240);
+ touch("com.example/cache/tomb/file2", kMbInBytes, 240);
+ mkdir("com.example/cache/tomb/dir");
+ touch("com.example/cache/tomb/dir/file1", kMbInBytes, 240);
+ touch("com.example/cache/tomb/dir/file2", kMbInBytes, 240);
+ mkdir("com.example/cache/tomb/atomic");
+ touch("com.example/cache/tomb/atomic/file1", kMbInBytes, 60);
+ touch("com.example/cache/tomb/atomic/file2", kMbInBytes, 60);
+ mkdir("com.example/cache/tomb/atomic/dir");
+ touch("com.example/cache/tomb/atomic/dir/file1", kMbInBytes, 60);
+ touch("com.example/cache/tomb/atomic/dir/file2", kMbInBytes, 60);
+
+ setxattr("com.example/cache/atomic", "user.cache_atomic");
+ setxattr("com.example/cache/atomic/tomb", "user.cache_tombstone");
+ setxattr("com.example/cache/tomb", "user.cache_tombstone");
+ setxattr("com.example/cache/tomb/atomic", "user.cache_atomic");
+
+ service->freeCache(testUuid, free() + kKbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/file2"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/dir/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/dir/file2"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/tomb/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/tomb/file2"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/tomb/dir/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/atomic/tomb/dir/file2"));
+
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file2"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file2"));
+
+ service->freeCache(testUuid, free() + kKbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, size("com.example/cache/atomic/file1"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/file2"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/dir/file1"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/dir/file2"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/file1"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/file2"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/dir/file2"));
+
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/file2"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file1"));
+ EXPECT_EQ(kMbInBytes, size("com.example/cache/tomb/dir/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file2"));
+
+ service->freeCache(testUuid, kTbInBytes,
+ FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+
+ EXPECT_EQ(-1, size("com.example/cache/atomic/file1"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/file2"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/dir/file1"));
+ EXPECT_EQ(-1, size("com.example/cache/atomic/dir/file2"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/file1"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/file2"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/atomic/tomb/dir/file2"));
+
+ EXPECT_EQ(0, size("com.example/cache/tomb/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/dir/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/file2"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file1"));
+ EXPECT_EQ(0, size("com.example/cache/tomb/atomic/dir/file2"));
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 947cc0d..4b68574 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -29,6 +29,7 @@
#define TEST_DATA_DIR "/data/"
#define TEST_APP_DIR "/data/app/"
#define TEST_APP_PRIVATE_DIR "/data/app-private/"
+#define TEST_APP_EPHEMERAL_DIR "/data/app-ephemeral/"
#define TEST_ASEC_DIR "/mnt/asec/"
#define TEST_EXPAND_DIR "/mnt/expand/"
@@ -57,6 +58,9 @@
android_app_private_dir.path = (char*) TEST_APP_PRIVATE_DIR;
android_app_private_dir.len = strlen(TEST_APP_PRIVATE_DIR);
+ android_app_ephemeral_dir.path = (char*) TEST_APP_EPHEMERAL_DIR;
+ android_app_ephemeral_dir.len = strlen(TEST_APP_EPHEMERAL_DIR);
+
android_data_dir.path = (char*) TEST_DATA_DIR;
android_data_dir.len = strlen(TEST_DATA_DIR);
@@ -85,19 +89,19 @@
// Bad prefixes directories
const char *badprefix1 = "/etc/passwd";
EXPECT_EQ(-1, validate_apk_path(badprefix1))
- << badprefix1 << " should be allowed as a valid path";
+ << badprefix1 << " should not be allowed as a valid path";
const char *badprefix2 = "../.." TEST_APP_DIR "../../../blah";
EXPECT_EQ(-1, validate_apk_path(badprefix2))
- << badprefix2 << " should be allowed as a valid path";
+ << badprefix2 << " should not be allowed as a valid path";
const char *badprefix3 = "init.rc";
EXPECT_EQ(-1, validate_apk_path(badprefix3))
- << badprefix3 << " should be allowed as a valid path";
+ << badprefix3 << " should not be allowed as a valid path";
const char *badprefix4 = "/init.rc";
EXPECT_EQ(-1, validate_apk_path(badprefix4))
- << badprefix4 << " should be allowed as a valid path";
+ << badprefix4 << " should not be allowed as a valid path";
}
TEST_F(UtilsTest, IsValidApkPath_Internal) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 37215ea..6d50f55 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -33,6 +33,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <cutils/fs.h>
+#include <cutils/properties.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -155,6 +156,9 @@
std::string create_data_path(const char* volume_uuid) {
if (volume_uuid == nullptr) {
return "/data";
+ } else if (!strcmp(volume_uuid, "TEST")) {
+ CHECK(property_get_bool("ro.debuggable", false));
+ return "/data/local/tmp";
} else {
CHECK(is_valid_filename(volume_uuid));
return StringPrintf("/mnt/expand/%s", volume_uuid);
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 5226d1c..aa83dc2 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -66,6 +66,8 @@
constexpr const char* kXattrInodeCache = "user.inode_cache";
constexpr const char* kXattrInodeCodeCache = "user.inode_code_cache";
+constexpr const char* kXattrCacheAtomic = "user.cache_atomic";
+constexpr const char* kXattrCacheTombstone = "user.cache_tombstone";
int create_pkg_path(char path[PKG_PATH_MAX],
const char *pkgname,
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index ce058c8..6fd9b21 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -469,9 +469,17 @@
return status;
}
+void signalHandler(int sig) {
+ if (sig == SIGINT) {
+ int retVal;
+ pthread_exit(&retVal);
+ }
+}
+
} // namespace lshal
} // namespace android
int main(int argc, char **argv) {
+ signal(SIGINT, ::android::lshal::signalHandler);
return ::android::lshal::Lshal{}.main(argc, argv);
}
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index 001c3d6..ca477bf 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -29,7 +29,8 @@
class BackgroundTaskState {
public:
- BackgroundTaskState(){}
+ BackgroundTaskState(std::function<void(void)> &&func)
+ : mFunc(std::forward<decltype(func)>(func)) {}
void notify() {
std::unique_lock<std::mutex> lock(mMutex);
mFinished = true;
@@ -42,22 +43,37 @@
mCondVar.wait_until(lock, end, [this](){ return this->mFinished; });
return mFinished;
}
+ void operator()() {
+ mFunc();
+ }
private:
std::mutex mMutex;
std::condition_variable mCondVar;
bool mFinished = false;
+ std::function<void(void)> mFunc;
};
+void *callAndNotify(void *data) {
+ BackgroundTaskState &state = *static_cast<BackgroundTaskState *>(data);
+ state();
+ state.notify();
+ return NULL;
+}
+
template<class R, class P>
-bool timeout(std::chrono::duration<R, P> delay, const std::function<void(void)> &func) {
+bool timeout(std::chrono::duration<R, P> delay, std::function<void(void)> &&func) {
auto now = std::chrono::system_clock::now();
- BackgroundTaskState state{};
- std::thread t([&state, &func] {
- func();
- state.notify();
- });
- t.detach();
+ BackgroundTaskState state{std::forward<decltype(func)>(func)};
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, callAndNotify, &state)) {
+ std::cerr << "FATAL: could not create background thread." << std::endl;
+ return false;
+ }
bool success = state.wait(now + delay);
+ if (!success) {
+ pthread_kill(thread, SIGINT);
+ }
+ pthread_join(thread, NULL);
return success;
}
diff --git a/include/ui/ANativeObjectBase.h b/include/ui/ANativeObjectBase.h
index 76e850f..640e34b 100644
--- a/include/ui/ANativeObjectBase.h
+++ b/include/ui/ANativeObjectBase.h
@@ -18,9 +18,7 @@
#define ANDROID_ANDROID_NATIVES_H
#include <sys/types.h>
-#include <string.h>
-#include <hardware/gralloc.h>
#include <system/window.h>
// ---------------------------------------------------------------------------
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index 842806e..94caf6b 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -19,9 +19,8 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Timers.h>
-#include <ui/PixelFormat.h>
+#include <utils/Timers.h>
namespace android {
diff --git a/include/ui/Gralloc1.h b/include/ui/Gralloc1.h
index 640e29c..90713b3 100644
--- a/include/ui/Gralloc1.h
+++ b/include/ui/Gralloc1.h
@@ -19,10 +19,17 @@
#define GRALLOC1_LOG_TAG "Gralloc1"
-#include <ui/Gralloc1On0Adapter.h>
-
+#include <functional>
+#include <memory>
#include <unordered_set>
+#include <log/log.h>
+
+#include <ui/Fence.h>
+
+#include <hardware/gralloc1.h>
+
+
namespace std {
template <>
struct hash<gralloc1_capability_t> {
@@ -33,10 +40,42 @@
}
namespace android {
-
+class GraphicBuffer;
class Fence;
class GraphicBuffer;
+class Gralloc1On0Adapter;
+} // namespace android
+
+// This is not an "official" capability (i.e., it is not found in gralloc1.h),
+// but we will use it to detect that we are running through the adapter, which
+// is capable of collaborating with GraphicBuffer such that queries on a
+// buffer_handle_t succeed
+static const auto GRALLOC1_CAPABILITY_ON_ADAPTER =
+ static_cast<gralloc1_capability_t>(GRALLOC1_LAST_CAPABILITY + 1);
+
+static const auto GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER =
+ static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 1);
+static const auto GRALLOC1_FUNCTION_ALLOCATE_WITH_ID =
+ static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 2);
+static const auto GRALLOC1_FUNCTION_LOCK_YCBCR =
+ static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 3);
+static const auto GRALLOC1_LAST_ADAPTER_FUNCTION = GRALLOC1_FUNCTION_LOCK_YCBCR;
+
+typedef gralloc1_error_t (*GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER)(
+ gralloc1_device_t* device, const android::GraphicBuffer* buffer);
+typedef gralloc1_error_t (*GRALLOC1_PFN_ALLOCATE_WITH_ID)(
+ gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptor,
+ gralloc1_backing_store_t id, buffer_handle_t* outBuffer);
+typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_LOCK_YCBCR)(
+ gralloc1_device_t* device, buffer_handle_t buffer,
+ uint64_t /*gralloc1_producer_usage_t*/ producerUsage,
+ uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage,
+ const gralloc1_rect_t* accessRegion, struct android_ycbcr* outYCbCr,
+ int32_t acquireFence);
+
+
+namespace android {
namespace Gralloc1 {
class Device;
diff --git a/include/ui/Gralloc1On0Adapter.h b/include/ui/Gralloc1On0Adapter.h
index b09fdc6..6379a08 100644
--- a/include/ui/Gralloc1On0Adapter.h
+++ b/include/ui/Gralloc1On0Adapter.h
@@ -35,33 +35,6 @@
struct gralloc_module_t;
-// This is not an "official" capability (i.e., it is not found in gralloc1.h),
-// but we will use it to detect that we are running through the adapter, which
-// is capable of collaborating with GraphicBuffer such that queries on a
-// buffer_handle_t succeed
-static const auto GRALLOC1_CAPABILITY_ON_ADAPTER =
- static_cast<gralloc1_capability_t>(GRALLOC1_LAST_CAPABILITY + 1);
-
-static const auto GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER =
- static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 1);
-static const auto GRALLOC1_FUNCTION_ALLOCATE_WITH_ID =
- static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 2);
-static const auto GRALLOC1_FUNCTION_LOCK_YCBCR =
- static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 3);
-static const auto GRALLOC1_LAST_ADAPTER_FUNCTION = GRALLOC1_FUNCTION_LOCK_YCBCR;
-
-typedef gralloc1_error_t (*GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER)(
- gralloc1_device_t* device, const android::GraphicBuffer* buffer);
-typedef gralloc1_error_t (*GRALLOC1_PFN_ALLOCATE_WITH_ID)(
- gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptor,
- gralloc1_backing_store_t id, buffer_handle_t* outBuffer);
-typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_LOCK_YCBCR)(
- gralloc1_device_t* device, buffer_handle_t buffer,
- uint64_t /*gralloc1_producer_usage_t*/ producerUsage,
- uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage,
- const gralloc1_rect_t* accessRegion, struct android_ycbcr* outYCbCr,
- int32_t acquireFence);
-
namespace android {
class Gralloc1On0Adapter : public gralloc1_device_t
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
index 5a23b68..5a0d64b 100644
--- a/include/ui/GrallocMapper.h
+++ b/include/ui/GrallocMapper.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_UI_GRALLOC_MAPPER_H
#define ANDROID_UI_GRALLOC_MAPPER_H
-#include <memory>
-
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <system/window.h>
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 759c9ec..040d1e7 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -20,13 +20,15 @@
#include <stdint.h>
#include <sys/types.h>
+#include <string>
+
#include <ui/ANativeObjectBase.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <utils/Flattenable.h>
#include <utils/RefBase.h>
-#include <string>
+#include <hardware/gralloc.h>
struct ANativeWindowBuffer;
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 2ccc44b..e97122b 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -20,11 +20,14 @@
#include <stdint.h>
+#include <memory>
+#include <string>
+
#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
-#include <utils/threads.h>
+#include <utils/Mutex.h>
#include <utils/Singleton.h>
#include <ui/Gralloc1.h>
@@ -36,7 +39,6 @@
class Allocator;
}
-class Gralloc1Loader;
class GraphicBufferMapper;
class String8;
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index 001769f..b6d4021 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -20,10 +20,18 @@
#include <stdint.h>
#include <sys/types.h>
+#include <memory>
+
#include <ui/Gralloc1.h>
#include <utils/Singleton.h>
+
+// Needed by code that still uses the GRALLOC_USAGE_* constants.
+// when/if we get rid of gralloc, we should provide aliases or fix call sites.
+#include <hardware/gralloc.h>
+
+
namespace android {
// ---------------------------------------------------------------------------
diff --git a/libs/ui/Gralloc1.cpp b/libs/ui/Gralloc1.cpp
index 7952ed6..64a8b40 100644
--- a/libs/ui/Gralloc1.cpp
+++ b/libs/ui/Gralloc1.cpp
@@ -18,6 +18,7 @@
#include <ui/Gralloc1.h>
#include <ui/GraphicBuffer.h>
+#include <ui/Gralloc1On0Adapter.h>
#include <vector>
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index 4cc0e4b..b8bc6c4 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -18,10 +18,13 @@
#define LOG_TAG "Gralloc1On0Adapter"
//#define LOG_NDEBUG 0
+#include <ui/Gralloc1On0Adapter.h>
+
+
#include <hardware/gralloc.h>
-#include <ui/Gralloc1On0Adapter.h>
#include <ui/GraphicBuffer.h>
+#include <ui/Gralloc1.h>
#include <utils/Log.h>
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
index ca67990..5c5d5b3 100644
--- a/libs/ui/GrallocAllocator.cpp
+++ b/libs/ui/GrallocAllocator.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "GrallocAllocator"
-#include <log/log.h>
#include <ui/GrallocAllocator.h>
+#include <log/log.h>
+
namespace android {
namespace Gralloc2 {
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
index b9e9040..6884dcb 100644
--- a/libs/ui/GrallocMapper.cpp
+++ b/libs/ui/GrallocMapper.cpp
@@ -16,11 +16,9 @@
#define LOG_TAG "GrallocMapper"
-#include <array>
-#include <string>
+#include <ui/GrallocMapper.h>
#include <log/log.h>
-#include <ui/GrallocMapper.h>
namespace android {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index b544426..37ebfb3 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -16,18 +16,10 @@
#define LOG_TAG "GraphicBuffer"
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/GrallocMapper.h>
#include <ui/GraphicBuffer.h>
+#include <ui/GrallocMapper.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
-#include <ui/PixelFormat.h>
namespace android {
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index b14110e..3f18bbc 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -18,13 +18,15 @@
#define LOG_TAG "GraphicBufferAllocator"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <ui/GraphicBufferAllocator.h>
+
+#include <stdio.h>
+
#include <log/log.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
#include <utils/Trace.h>
-#include <ui/GraphicBufferAllocator.h>
-#include <ui/Gralloc1On0Adapter.h>
#include <ui/GrallocAllocator.h>
#include <ui/GrallocMapper.h>
#include <ui/GraphicBufferMapper.h>
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index f418f7f..656472f 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -18,8 +18,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
-#include <stdint.h>
-#include <errno.h>
+#include <ui/GraphicBufferMapper.h>
// We would eliminate the non-conforming zero-length array, but we can't since
// this is effectively included from the Linux kernel
@@ -28,13 +27,10 @@
#include <sync/sync.h>
#pragma clang diagnostic pop
-#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Trace.h>
-#include <ui/Gralloc1On0Adapter.h>
#include <ui/GrallocMapper.h>
-#include <ui/GraphicBufferMapper.h>
#include <ui/GraphicBuffer.h>
#include <system/graphics.h>
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 5309acf..bb70c5c 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -25,7 +25,13 @@
DisplayService::DisplayService(Hwc2::Composer* hidl)
: BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
- hardware_composer_(hidl) {}
+ hardware_composer_(hidl) {
+ hardware_composer_.Initialize();
+}
+
+bool DisplayService::IsInitialized() const {
+ return BASE::IsInitialized() && hardware_composer_.IsInitialized();
+}
std::string DisplayService::DumpState(size_t max_length) {
std::vector<char> buffer(max_length);
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 5de4f1d..b207e4d 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -23,6 +23,7 @@
// DisplayService implements the displayd display service over ServiceFS.
class DisplayService : public pdx::ServiceBase<DisplayService> {
public:
+ bool IsInitialized() const override;
std::string DumpState(size_t max_length) override;
void OnChannelClose(pdx::Message& message,
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index e6ed665..f801d9b 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -100,7 +100,8 @@
}
HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
- : hwc2_hidl_(hwc2_hidl),
+ : initialized_(false),
+ hwc2_hidl_(hwc2_hidl),
display_transform_(HWC_TRANSFORM_NONE),
display_surfaces_updated_(false),
hardware_layers_need_update_(false),
@@ -126,6 +127,51 @@
Suspend();
}
+bool HardwareComposer::Initialize() {
+ if (initialized_) {
+ ALOGE("HardwareComposer::Initialize: already initialized.");
+ return false;
+ }
+
+ int32_t ret = HWC2_ERROR_NONE;
+
+ Hwc2::Config config;
+ ret = (int32_t)hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+
+ if (ret != HWC2_ERROR_NONE) {
+ ALOGE("HardwareComposer: Failed to get current display config : %d",
+ config);
+ return false;
+ }
+
+ ret =
+ GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
+
+ if (ret != HWC2_ERROR_NONE) {
+ ALOGE(
+ "HardwareComposer: Failed to get display attributes for current "
+ "configuration : %d",
+ ret);
+ return false;
+ }
+
+ ALOGI(
+ "HardwareComposer: primary display attributes: width=%d height=%d "
+ "vsync_period_ns=%d DPI=%dx%d",
+ native_display_metrics_.width, native_display_metrics_.height,
+ native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
+ native_display_metrics_.dpi.y);
+
+ // Set the display metrics but never use rotation to avoid the long latency of
+ // rotation processing in hwc.
+ display_transform_ = HWC_TRANSFORM_NONE;
+ display_metrics_ = native_display_metrics_;
+
+ initialized_ = true;
+
+ return initialized_;
+}
+
bool HardwareComposer::Resume() {
std::lock_guard<std::mutex> post_thread_lock(post_thread_state_mutex_);
if (post_thread_state_ == PostThreadState::kRunning) {
@@ -136,62 +182,6 @@
int32_t ret = HWC2_ERROR_NONE;
- static const uint32_t attributes[] = {
- HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_DPI_X, HWC_DISPLAY_DPI_Y, HWC_DISPLAY_NO_ATTRIBUTE,
- };
-
- std::vector<Hwc2::Config> configs;
- ret = (int32_t)hwc2_hidl_->getDisplayConfigs(HWC_DISPLAY_PRIMARY, &configs);
-
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display configs");
- return false;
- }
-
- uint32_t num_configs = configs.size();
-
- for (size_t i = 0; i < num_configs; i++) {
- ALOGI("HardwareComposer: cfg[%zd/%zd] = 0x%08x", i, num_configs,
- configs[i]);
-
- ret = GetDisplayMetrics(HWC_DISPLAY_PRIMARY, configs[i],
- &native_display_metrics_);
-
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display attributes %d", ret);
- continue;
- } else {
- ret =
- (int32_t)hwc2_hidl_->setActiveConfig(HWC_DISPLAY_PRIMARY, configs[i]);
-
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to set display configuration; ret=%d",
- ret);
- continue;
- }
-
- break;
- }
- }
-
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Could not set a valid display configuration.");
- return false;
- }
-
- // Set the display metrics but never use rotation to avoid the long latency of
- // rotation processing in hwc.
- display_transform_ = HWC_TRANSFORM_NONE;
- display_metrics_ = native_display_metrics_;
-
- ALOGI(
- "HardwareComposer: primary display attributes: width=%d height=%d "
- "vsync_period_ns=%d DPI=%dx%d",
- native_display_metrics_.width, native_display_metrics_.height,
- native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
- native_display_metrics_.dpi.y);
-
// Always turn off vsync when we start.
EnableVsync(false);
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index b6aa807..e2a8b90 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -189,6 +189,10 @@
HardwareComposer(Hwc2::Composer* hidl);
~HardwareComposer();
+ bool Initialize();
+
+ bool IsInitialized() const { return initialized_; }
+
bool Suspend();
bool Resume();
@@ -303,6 +307,8 @@
void HandlePendingScreenshots();
+ bool initialized_;
+
// Hardware composer HAL device.
std::unique_ptr<Hwc2::Composer> hwc2_hidl_;
sp<ComposerCallback> callbacks_;
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index 18ec5e3..7062c57 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -246,6 +246,19 @@
*/
static int getNeededCount(GLint pname) {
int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+ // GLES 3.x pnames
+ switch (pname) {
+ case GL_MAX_VIEWPORT_DIMS:
+ needed = 2;
+ break;
+
+ case GL_PROGRAM_BINARY_FORMATS:
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+ break;
+ }
+#endif
+
#ifdef GL_ES_VERSION_2_0
// GLES 2.x pnames
switch (pname) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 215628d..2781e8c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2539,11 +2539,18 @@
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
- if (index < 0) {
+ // As a matter of normal operation, the LayerCleaner will produce a second
+ // attempt to remove the surface. The Layer will be kept alive in mDrawingState
+ // so we will succeed in promoting it, but it's already been removed
+ // from mCurrentState. As long as we can find it in mDrawingState we have no problem
+ // otherwise something has gone wrong and we are leaking the layer.
+ if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
ALOGE("Failed to find layer (%s) in layer parent (%s).",
layer->getName().string(),
(p != nullptr) ? p->getName().string() : "no-parent");
return BAD_VALUE;
+ } else if (index < 0) {
+ return NO_ERROR;
}
mLayersPendingRemoval.add(layer);
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index e6ab29a..5aaaab1 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2325,11 +2325,18 @@
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
- if (index < 0) {
+ // As a matter of normal operation, the LayerCleaner will produce a second
+ // attempt to remove the surface. The Layer will be kept alive in mDrawingState
+ // so we will succeed in promoting it, but it's already been removed
+ // from mCurrentState. As long as we can find it in mDrawingState we have no problem
+ // otherwise something has gone wrong and we are leaking the layer.
+ if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
ALOGE("Failed to find layer (%s) in layer parent (%s).",
layer->getName().string(),
(p != nullptr) ? p->getName().string() : "no-parent");
return BAD_VALUE;
+ } else if (index < 0) {
+ return NO_ERROR;
}
mLayersPendingRemoval.add(layer);