• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <sstream>
18 #include <string>
19 
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/statvfs.h>
24 #include <sys/stat.h>
25 #include <sys/xattr.h>
26 
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <android-base/properties.h>
30 #include <android-base/scopeguard.h>
31 #include <android-base/stringprintf.h>
32 #include <cutils/properties.h>
33 #include <gtest/gtest.h>
34 
35 #include "binder_test_utils.h"
36 #include "InstalldNativeService.h"
37 #include "dexopt.h"
38 #include "globals.h"
39 #include "utils.h"
40 
41 using android::base::StringPrintf;
42 
43 namespace android {
44 namespace installd {
45 
46 constexpr const char* kTestUuid = "TEST";
47 
48 #define FLAG_FORCE InstalldNativeService::FLAG_FORCE
49 
get_property(const char * key,char * value,const char * default_value)50 int get_property(const char *key, char *value, const char *default_value) {
51     return property_get(key, value, default_value);
52 }
53 
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)54 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
55         const char *instruction_set) {
56     return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
57 }
58 
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)59 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
60         const char *instruction_set) {
61     return calculate_odex_file_path_default(path, apk_path, instruction_set);
62 }
63 
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)64 bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
65     return create_cache_path_default(path, src, instruction_set);
66 }
67 
get_full_path(const char * path)68 static std::string get_full_path(const char* path) {
69     return StringPrintf("/data/local/tmp/user/0/%s", path);
70 }
71 
mkdir(const char * path,uid_t owner,gid_t group,mode_t mode)72 static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
73     const std::string fullPath = get_full_path(path);
74     EXPECT_EQ(::mkdir(fullPath.c_str(), mode), 0);
75     EXPECT_EQ(::chown(fullPath.c_str(), owner, group), 0);
76     EXPECT_EQ(::chmod(fullPath.c_str(), mode), 0);
77 }
78 
touch(const char * path,uid_t owner,gid_t group,mode_t mode)79 static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
80     int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
81     EXPECT_NE(fd, -1);
82     EXPECT_EQ(::fchown(fd, owner, group), 0);
83     EXPECT_EQ(::fchmod(fd, mode), 0);
84     EXPECT_EQ(::close(fd), 0);
85 }
86 
stat_gid(const char * path)87 static int stat_gid(const char* path) {
88     struct stat buf;
89     EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
90     return buf.st_gid;
91 }
92 
stat_mode(const char * path)93 static int stat_mode(const char* path) {
94     struct stat buf;
95     EXPECT_EQ(::stat(get_full_path(path).c_str(), &buf), 0);
96     return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
97 }
98 
99 class ServiceTest : public testing::Test {
100 protected:
101     InstalldNativeService* service;
102     std::unique_ptr<std::string> testUuid;
103 
SetUp()104     virtual void SetUp() {
105         setenv("ANDROID_LOG_TAGS", "*:v", 1);
106         android::base::InitLogging(nullptr);
107 
108         service = new InstalldNativeService();
109         testUuid = std::make_unique<std::string>();
110         *testUuid = std::string(kTestUuid);
111         system("mkdir -p /data/local/tmp/user/0");
112 
113         init_globals_from_data_and_root();
114     }
115 
TearDown()116     virtual void TearDown() {
117         delete service;
118         system("rm -rf /data/local/tmp/user");
119     }
120 };
121 
TEST_F(ServiceTest,FixupAppData_Upgrade)122 TEST_F(ServiceTest, FixupAppData_Upgrade) {
123     LOG(INFO) << "FixupAppData_Upgrade";
124 
125     mkdir("com.example", 10000, 10000, 0700);
126     mkdir("com.example/normal", 10000, 10000, 0700);
127     mkdir("com.example/cache", 10000, 10000, 0700);
128     touch("com.example/cache/file", 10000, 10000, 0700);
129 
130     service->fixupAppData(testUuid, 0);
131 
132     EXPECT_EQ(10000, stat_gid("com.example/normal"));
133     EXPECT_EQ(20000, stat_gid("com.example/cache"));
134     EXPECT_EQ(20000, stat_gid("com.example/cache/file"));
135 
136     EXPECT_EQ(0700, stat_mode("com.example/normal"));
137     EXPECT_EQ(02771, stat_mode("com.example/cache"));
138     EXPECT_EQ(0700, stat_mode("com.example/cache/file"));
139 }
140 
TEST_F(ServiceTest,FixupAppData_Moved)141 TEST_F(ServiceTest, FixupAppData_Moved) {
142     LOG(INFO) << "FixupAppData_Moved";
143 
144     mkdir("com.example", 10000, 10000, 0700);
145     mkdir("com.example/foo", 10000, 10000, 0700);
146     touch("com.example/foo/file", 10000, 20000, 0700);
147     mkdir("com.example/bar", 10000, 20000, 0700);
148     touch("com.example/bar/file", 10000, 20000, 0700);
149 
150     service->fixupAppData(testUuid, 0);
151 
152     EXPECT_EQ(10000, stat_gid("com.example/foo"));
153     EXPECT_EQ(20000, stat_gid("com.example/foo/file"));
154     EXPECT_EQ(10000, stat_gid("com.example/bar"));
155     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
156 
157     service->fixupAppData(testUuid, FLAG_FORCE);
158 
159     EXPECT_EQ(10000, stat_gid("com.example/foo"));
160     EXPECT_EQ(10000, stat_gid("com.example/foo/file"));
161     EXPECT_EQ(10000, stat_gid("com.example/bar"));
162     EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
163 }
164 
TEST_F(ServiceTest,HashSecondaryDex)165 TEST_F(ServiceTest, HashSecondaryDex) {
166     LOG(INFO) << "HashSecondaryDex";
167 
168     mkdir("com.example", 10000, 10000, 0700);
169     mkdir("com.example/foo", 10000, 10000, 0700);
170     touch("com.example/foo/file", 10000, 20000, 0700);
171 
172     std::vector<uint8_t> result;
173     std::string dexPath = get_full_path("com.example/foo/file");
174     EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
175         dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
176 
177     EXPECT_EQ(result.size(), 32U);
178 
179     std::ostringstream output;
180     output << std::hex << std::setfill('0');
181     for (auto b : result) {
182         output << std::setw(2) << +b;
183     }
184 
185     // This is the SHA256 of an empty string (sha256sum /dev/null)
186     EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
187 }
188 
TEST_F(ServiceTest,HashSecondaryDex_NoSuch)189 TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
190     LOG(INFO) << "HashSecondaryDex_NoSuch";
191 
192     std::vector<uint8_t> result;
193     std::string dexPath = get_full_path("com.example/foo/file");
194     EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
195         dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
196 
197     EXPECT_EQ(result.size(), 0U);
198 }
199 
TEST_F(ServiceTest,HashSecondaryDex_Unreadable)200 TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
201     LOG(INFO) << "HashSecondaryDex_Unreadable";
202 
203     mkdir("com.example", 10000, 10000, 0700);
204     mkdir("com.example/foo", 10000, 10000, 0700);
205     touch("com.example/foo/file", 10000, 20000, 0300);
206 
207     std::vector<uint8_t> result;
208     std::string dexPath = get_full_path("com.example/foo/file");
209     EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
210         dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
211 
212     EXPECT_EQ(result.size(), 0U);
213 }
214 
TEST_F(ServiceTest,HashSecondaryDex_WrongApp)215 TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
216     LOG(INFO) << "HashSecondaryDex_WrongApp";
217 
218     mkdir("com.example", 10000, 10000, 0700);
219     mkdir("com.example/foo", 10000, 10000, 0700);
220     touch("com.example/foo/file", 10000, 20000, 0700);
221 
222     std::vector<uint8_t> result;
223     std::string dexPath = get_full_path("com.example/foo/file");
224     EXPECT_BINDER_FAIL(service->hashSecondaryDexFile(
225         dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result));
226 }
227 
TEST_F(ServiceTest,CalculateOat)228 TEST_F(ServiceTest, CalculateOat) {
229     char buf[PKG_PATH_MAX];
230 
231     EXPECT_TRUE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file.apk", "isa"));
232     EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
233 
234     EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "/path/to/file", "isa"));
235     EXPECT_FALSE(calculate_oat_file_path(buf, "/path/to/oat", "file", "isa"));
236 }
237 
TEST_F(ServiceTest,CalculateOdex)238 TEST_F(ServiceTest, CalculateOdex) {
239     char buf[PKG_PATH_MAX];
240 
241     EXPECT_TRUE(calculate_odex_file_path(buf, "/path/to/file.apk", "isa"));
242     EXPECT_EQ("/path/to/oat/isa/file.odex", std::string(buf));
243 }
244 
TEST_F(ServiceTest,CalculateCache)245 TEST_F(ServiceTest, CalculateCache) {
246     char buf[PKG_PATH_MAX];
247 
248     EXPECT_TRUE(create_cache_path(buf, "/path/to/file.apk", "isa"));
249     EXPECT_EQ("/data/dalvik-cache/isa/path@to@file.apk@classes.dex", std::string(buf));
250 }
251 
mkdirs(const std::string & path,mode_t mode)252 static bool mkdirs(const std::string& path, mode_t mode) {
253     struct stat sb;
254     if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
255         return true;
256     }
257 
258     if (!mkdirs(android::base::Dirname(path), mode)) {
259         return false;
260     }
261 
262     if (::mkdir(path.c_str(), mode) != 0) {
263         PLOG(DEBUG) << "Failed to create folder " << path;
264         return false;
265     }
266     return true;
267 }
268 
269 class AppDataSnapshotTest : public testing::Test {
270 private:
271     std::string rollback_ce_base_dir;
272     std::string rollback_de_base_dir;
273 
274 protected:
275     InstalldNativeService* service;
276 
277     std::string fake_package_ce_path;
278     std::string fake_package_de_path;
279 
SetUp()280     virtual void SetUp() {
281         setenv("ANDROID_LOG_TAGS", "*:v", 1);
282         android::base::InitLogging(nullptr);
283 
284         service = new InstalldNativeService();
285         ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
286 
287         init_globals_from_data_and_root();
288 
289         rollback_ce_base_dir = create_data_misc_ce_rollback_base_path("TEST", 0);
290         rollback_de_base_dir = create_data_misc_de_rollback_base_path("TEST", 0);
291 
292         fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
293         fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
294 
295         ASSERT_TRUE(mkdirs(rollback_ce_base_dir, 0700));
296         ASSERT_TRUE(mkdirs(rollback_de_base_dir, 0700));
297         ASSERT_TRUE(mkdirs(fake_package_ce_path, 0700));
298         ASSERT_TRUE(mkdirs(fake_package_de_path, 0700));
299     }
300 
TearDown()301     virtual void TearDown() {
302         ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_ce_base_dir, true));
303         ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_de_base_dir, true));
304         ASSERT_EQ(0, delete_dir_contents(fake_package_ce_path, true));
305         ASSERT_EQ(0, delete_dir_contents(fake_package_de_path, true));
306 
307         delete service;
308         ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user/0", true));
309     }
310 };
311 
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot)312 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot) {
313   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 37);
314   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 37);
315 
316   ASSERT_TRUE(android::base::WriteStringToFile(
317           "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
318           0700, 10000, 20000, false /* follow_symlinks */));
319   ASSERT_TRUE(android::base::WriteStringToFile(
320           "TEST_CONTENT_DE", fake_package_de_path + "/file1",
321           0700, 10000, 20000, false /* follow_symlinks */));
322 
323   // Request a snapshot of the CE content but not the DE content.
324   int64_t ce_snapshot_inode;
325   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
326           "com.foo", 0, 37, FLAG_STORAGE_CE, &ce_snapshot_inode));
327   struct stat buf;
328   memset(&buf, 0, sizeof(buf));
329   ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
330   ASSERT_EQ(ce_snapshot_inode, (int64_t) buf.st_ino);
331 
332   std::string ce_content, de_content;
333   // At this point, we should have the CE content but not the DE content.
334   ASSERT_TRUE(android::base::ReadFileToString(
335       rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
336   ASSERT_FALSE(android::base::ReadFileToString(
337       rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
338   ASSERT_EQ("TEST_CONTENT_CE", ce_content);
339 
340   // Modify the CE content, so we can assert later that it's reflected
341   // in the snapshot.
342   ASSERT_TRUE(android::base::WriteStringToFile(
343           "TEST_CONTENT_CE_MODIFIED", fake_package_ce_path + "/file1",
344           0700, 10000, 20000, false /* follow_symlinks */));
345 
346   // Request a snapshot of the DE content but not the CE content.
347   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
348           "com.foo", 0, 37, FLAG_STORAGE_DE, &ce_snapshot_inode));
349   // Only DE content snapshot was requested.
350   ASSERT_EQ(ce_snapshot_inode, 0);
351 
352   // At this point, both the CE as well as the DE content should be fully
353   // populated.
354   ASSERT_TRUE(android::base::ReadFileToString(
355       rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
356   ASSERT_TRUE(android::base::ReadFileToString(
357       rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
358   ASSERT_EQ("TEST_CONTENT_CE", ce_content);
359   ASSERT_EQ("TEST_CONTENT_DE", de_content);
360 
361   // Modify the DE content, so we can assert later that it's reflected
362   // in our final snapshot.
363   ASSERT_TRUE(android::base::WriteStringToFile(
364           "TEST_CONTENT_DE_MODIFIED", fake_package_de_path + "/file1",
365           0700, 10000, 20000, false /* follow_symlinks */));
366 
367   // Request a snapshot of both the CE as well as the DE content.
368   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
369           "com.foo", 0, 37, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
370 
371   ASSERT_TRUE(android::base::ReadFileToString(
372       rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
373   ASSERT_TRUE(android::base::ReadFileToString(
374       rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */));
375   ASSERT_EQ("TEST_CONTENT_CE_MODIFIED", ce_content);
376   ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
377 }
378 
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_TwoSnapshotsWithTheSameId)379 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_TwoSnapshotsWithTheSameId) {
380   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 67);
381   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 67);
382 
383   auto another_fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.bar");
384   auto another_fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.bar");
385 
386   // Since this test sets up data for another package, some bookkeeping is required.
387   auto deleter = [&]() {
388       ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_ce_path, true));
389       ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_de_path, true));
390   };
391   auto scope_guard = android::base::make_scope_guard(deleter);
392 
393   ASSERT_TRUE(mkdirs(another_fake_package_ce_path, 0700));
394   ASSERT_TRUE(mkdirs(another_fake_package_de_path, 0700));
395 
396   ASSERT_TRUE(android::base::WriteStringToFile(
397           "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
398           0700, 10000, 20000, false /* follow_symlinks */));
399   ASSERT_TRUE(android::base::WriteStringToFile(
400           "TEST_CONTENT_DE", fake_package_de_path + "/file1",
401           0700, 10000, 20000, false /* follow_symlinks */));
402   ASSERT_TRUE(android::base::WriteStringToFile(
403           "ANOTHER_TEST_CONTENT_CE", another_fake_package_ce_path + "/file1",
404           0700, 10000, 20000, false /* follow_symlinks */));
405   ASSERT_TRUE(android::base::WriteStringToFile(
406           "ANOTHER_TEST_CONTENT_DE", another_fake_package_de_path + "/file1",
407           0700, 10000, 20000, false /* follow_symlinks */));
408 
409   // Request snapshot for the package com.foo.
410   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
411           "com.foo", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
412   // Now request snapshot with the same id for the package com.bar
413   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
414           "com.bar", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
415 
416   // Check that both snapshots have correct data in them.
417   std::string com_foo_ce_content, com_foo_de_content;
418   std::string com_bar_ce_content, com_bar_de_content;
419   ASSERT_TRUE(android::base::ReadFileToString(
420       rollback_ce_dir + "/com.foo/file1", &com_foo_ce_content, false /* follow_symlinks */));
421   ASSERT_TRUE(android::base::ReadFileToString(
422       rollback_de_dir + "/com.foo/file1", &com_foo_de_content, false /* follow_symlinks */));
423   ASSERT_TRUE(android::base::ReadFileToString(
424       rollback_ce_dir + "/com.bar/file1", &com_bar_ce_content, false /* follow_symlinks */));
425   ASSERT_TRUE(android::base::ReadFileToString(
426       rollback_de_dir + "/com.bar/file1", &com_bar_de_content, false /* follow_symlinks */));
427   ASSERT_EQ("TEST_CONTENT_CE", com_foo_ce_content);
428   ASSERT_EQ("TEST_CONTENT_DE", com_foo_de_content);
429   ASSERT_EQ("ANOTHER_TEST_CONTENT_CE", com_bar_ce_content);
430   ASSERT_EQ("ANOTHER_TEST_CONTENT_DE", com_bar_de_content);
431 }
432 
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_AppDataAbsent)433 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_AppDataAbsent) {
434   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 73);
435   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 73);
436 
437   // Similuating app data absence.
438   ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_ce_path, true));
439   ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_de_path, true));
440 
441   int64_t ce_snapshot_inode;
442   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
443           "com.foo", 0, 73, FLAG_STORAGE_CE, &ce_snapshot_inode));
444   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
445           "com.foo", 0, 73, FLAG_STORAGE_DE, nullptr));
446   // No CE content snapshot was performed.
447   ASSERT_EQ(ce_snapshot_inode, 0);
448 
449   // The snapshot calls must succeed but there should be no snapshot
450   // created.
451   struct stat sb;
452   ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
453   ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
454 }
455 
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsExistingSnapshot)456 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
457   auto rollback_ce_dir = create_data_misc_ce_rollback_package_path("TEST", 0, 13, "com.foo");
458   auto rollback_de_dir = create_data_misc_de_rollback_package_path("TEST", 0, 13, "com.foo");
459 
460   ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
461   ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
462 
463   // Simulate presence of an existing snapshot
464   ASSERT_TRUE(android::base::WriteStringToFile(
465           "TEST_CONTENT_CE", rollback_ce_dir + "/file1",
466           0700, 10000, 20000, false /* follow_symlinks */));
467   ASSERT_TRUE(android::base::WriteStringToFile(
468           "TEST_CONTENT_DE", rollback_de_dir + "/file1",
469           0700, 10000, 20000, false /* follow_symlinks */));
470 
471   // Create app data.
472   ASSERT_TRUE(android::base::WriteStringToFile(
473           "TEST_CONTENT_2_CE", fake_package_ce_path + "/file2",
474           0700, 10000, 20000, false /* follow_symlinks */));
475   ASSERT_TRUE(android::base::WriteStringToFile(
476           "TEST_CONTENT_2_DE", fake_package_de_path + "/file2",
477           0700, 10000, 20000, false /* follow_symlinks */));
478 
479   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
480           "com.foo", 0, 13, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
481 
482   // Previous snapshot (with data for file1) must be cleared.
483   struct stat sb;
484   ASSERT_EQ(-1, stat((rollback_ce_dir + "/file1").c_str(), &sb));
485   ASSERT_EQ(-1, stat((rollback_de_dir + "/file1").c_str(), &sb));
486   // New snapshot (with data for file2) must be present.
487   ASSERT_NE(-1, stat((rollback_ce_dir + "/file2").c_str(), &sb));
488   ASSERT_NE(-1, stat((rollback_de_dir + "/file2").c_str(), &sb));
489 }
490 
TEST_F(AppDataSnapshotTest,SnapshotAppData_WrongVolumeUuid)491 TEST_F(AppDataSnapshotTest, SnapshotAppData_WrongVolumeUuid) {
492   // Setup rollback folders to make sure that fails due to wrong volumeUuid being
493   // passed, not because of some other reason.
494   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 17);
495   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 17);
496 
497   ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
498   ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
499 
500   EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
501           "com.foo", 0, 17, FLAG_STORAGE_DE, nullptr));
502 }
503 
TEST_F(AppDataSnapshotTest,CreateAppDataSnapshot_ClearsCache)504 TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsCache) {
505   auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
506   auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
507   auto fake_package_de_cache_path = fake_package_de_path + "/cache";
508   auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
509 
510   ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 0700));
511   ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 0700));
512   ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 0700));
513   ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 0700));
514 
515   ASSERT_TRUE(android::base::WriteStringToFile(
516           "TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
517           0700, 10000, 20000, false /* follow_symlinks */));
518   ASSERT_TRUE(android::base::WriteStringToFile(
519           "TEST_CONTENT_CE", fake_package_ce_code_cache_path + "/file1",
520           0700, 10000, 20000, false /* follow_symlinks */));
521   ASSERT_TRUE(android::base::WriteStringToFile(
522           "TEST_CONTENT_DE", fake_package_de_cache_path + "/file1",
523           0700, 10000, 20000, false /* follow_symlinks */));
524   ASSERT_TRUE(android::base::WriteStringToFile(
525           "TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
526           0700, 10000, 20000, false /* follow_symlinks */));
527   ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
528           "com.foo", 0, 23, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
529   // The snapshot call must clear cache.
530   struct stat sb;
531   ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
532   ASSERT_EQ(-1, stat((fake_package_ce_code_cache_path + "/file1").c_str(), &sb));
533   ASSERT_EQ(-1, stat((fake_package_de_cache_path + "/file1").c_str(), &sb));
534   ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
535 }
536 
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot)537 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot) {
538   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 239);
539   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 239);
540 
541   ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
542   ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
543 
544   // Write contents to the rollback location. We'll write the same files to the
545   // app data location and make sure the restore has overwritten them.
546   ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
547   ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
548   ASSERT_TRUE(android::base::WriteStringToFile(
549           "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
550           0700, 10000, 20000, false /* follow_symlinks */));
551   ASSERT_TRUE(android::base::WriteStringToFile(
552           "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
553           0700, 10000, 20000, false /* follow_symlinks */));
554   ASSERT_TRUE(android::base::WriteStringToFile(
555           "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
556           0700, 10000, 20000, false /* follow_symlinks */));
557   ASSERT_TRUE(android::base::WriteStringToFile(
558           "TEST_CONTENT_DE", fake_package_de_path + "/file1",
559           0700, 10000, 20000, false /* follow_symlinks */));
560 
561   ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
562           "com.foo", 10000, "", 0, 239, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
563 
564   std::string ce_content, de_content;
565   ASSERT_TRUE(android::base::ReadFileToString(
566       fake_package_ce_path + "/file1", &ce_content, false /* follow_symlinks */));
567   ASSERT_TRUE(android::base::ReadFileToString(
568       fake_package_de_path + "/file1", &de_content, false /* follow_symlinks */));
569   ASSERT_EQ("CE_RESTORE_CONTENT", ce_content);
570   ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
571 }
572 
TEST_F(AppDataSnapshotTest,CreateSnapshotThenDestroyIt)573 TEST_F(AppDataSnapshotTest, CreateSnapshotThenDestroyIt) {
574   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 57);
575   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 57);
576 
577   // Prepare data for snapshot.
578   ASSERT_TRUE(android::base::WriteStringToFile(
579           "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
580           0700, 10000, 20000, false /* follow_symlinks */));
581   ASSERT_TRUE(android::base::WriteStringToFile(
582           "TEST_CONTENT_DE", fake_package_de_path + "/file1",
583           0700, 10000, 20000, false /* follow_symlinks */));
584 
585   int64_t ce_snapshot_inode;
586   // Request a snapshot of both the CE as well as the DE content.
587   ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
588           "com.foo", 0, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
589   // Because CE data snapshot was requested, ce_snapshot_inode can't be null.
590   ASSERT_NE(0, ce_snapshot_inode);
591   // Check snapshot is there.
592   struct stat sb;
593   ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
594   ASSERT_EQ(0, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
595 
596 
597   ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
598           "com.foo", 0, ce_snapshot_inode, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
599   // Check snapshot is deleted.
600   ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
601   ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
602 }
603 
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_CeSnapshotInodeIsZero)604 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
605   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 1543);
606   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 1543);
607 
608   // Create a snapshot
609   ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
610   ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
611   ASSERT_TRUE(android::base::WriteStringToFile(
612           "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
613           0700, 10000, 20000, false /* follow_symlinks */));
614   ASSERT_TRUE(android::base::WriteStringToFile(
615           "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1",
616           0700, 10000, 20000, false /* follow_symlinks */));
617 
618   ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
619           "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
620 
621   // Check snapshot is deleted.
622   struct stat sb;
623   ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
624   ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
625 
626   // Check that deleting already deleted snapshot is no-op.
627   ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
628           "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
629 }
630 
TEST_F(AppDataSnapshotTest,DestroyAppDataSnapshot_WrongVolumeUuid)631 TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
632   // Setup rollback data to make sure that test fails due to wrong volumeUuid
633   // being passed, not because of some other reason.
634   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 43);
635   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 43);
636 
637   ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
638   ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
639 
640   ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_unique<std::string>("BAR"),
641           "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
642 }
643 
TEST_F(AppDataSnapshotTest,RestoreAppDataSnapshot_WrongVolumeUuid)644 TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
645   // Setup rollback data to make sure that fails due to wrong volumeUuid being
646   // passed, not because of some other reason.
647   auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 41);
648   auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 41);
649 
650   ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
651   ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
652 
653   EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
654           "com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
655 }
656 
657 }  // namespace installd
658 }  // namespace android
659