-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'cm-11.0' of github.com:CyanogenMod/android_frameworks_n…
…ative into HEAD
- Loading branch information
Showing
32 changed files
with
1,683 additions
and
437 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright (C) 2012 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. | ||
|
||
LOCAL_PATH:= $(call my-dir) | ||
include $(CLEAR_VARS) | ||
|
||
LOCAL_SRC_FILES := idmap.cpp create.cpp scan.cpp inspect.cpp | ||
|
||
LOCAL_SHARED_LIBRARIES := liblog libutils libandroidfw | ||
|
||
LOCAL_MODULE := idmap | ||
|
||
LOCAL_C_INCLUDES := external/zlib | ||
|
||
LOCAL_MODULE_TAGS := optional | ||
|
||
include $(BUILD_EXECUTABLE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
#include "idmap.h" | ||
|
||
#include <androidfw/AssetManager.h> | ||
#include <androidfw/ResourceTypes.h> | ||
#include <androidfw/ZipFileRO.h> | ||
#include <utils/String8.h> | ||
|
||
#include <fcntl.h> | ||
#include <sys/stat.h> | ||
|
||
using namespace android; | ||
|
||
namespace { | ||
int get_zip_entry_crc(const char *zip_path, const char *entry_name, uint32_t *crc) | ||
{ | ||
ZipFileRO zip; | ||
if (zip.open(zip_path) != NO_ERROR) { | ||
return -1; | ||
} | ||
const ZipEntryRO entry = zip.findEntryByName(entry_name); | ||
if (entry == NULL) { | ||
return -1; | ||
} | ||
if (!zip.getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)crc)) { | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
int open_idmap(const char *path) | ||
{ | ||
int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)); | ||
if (fd == -1) { | ||
ALOGD("error: open %s: %s\n", path, strerror(errno)); | ||
goto fail; | ||
} | ||
if (fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { | ||
ALOGD("error: fchmod %s: %s\n", path, strerror(errno)); | ||
goto fail; | ||
} | ||
if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) { | ||
ALOGD("error: flock %s: %s\n", path, strerror(errno)); | ||
goto fail; | ||
} | ||
|
||
return fd; | ||
fail: | ||
if (fd != -1) { | ||
close(fd); | ||
unlink(path); | ||
} | ||
return -1; | ||
} | ||
|
||
int write_idmap(int fd, const uint32_t *data, size_t size) | ||
{ | ||
if (lseek(fd, SEEK_SET, 0) < 0) { | ||
return -1; | ||
} | ||
size_t bytesLeft = size; | ||
while (bytesLeft > 0) { | ||
ssize_t w = TEMP_FAILURE_RETRY(write(fd, data + size - bytesLeft, bytesLeft)); | ||
if (w < 0) { | ||
fprintf(stderr, "error: write: %s\n", strerror(errno)); | ||
return -1; | ||
} | ||
bytesLeft -= w; | ||
} | ||
return 0; | ||
} | ||
|
||
bool is_idmap_stale_fd(const char *target_apk_path, const char *overlay_apk_path, int idmap_fd) | ||
{ | ||
static const size_t N = ResTable::IDMAP_HEADER_SIZE_BYTES; | ||
struct stat st; | ||
if (fstat(idmap_fd, &st) == -1) { | ||
return true; | ||
} | ||
if (st.st_size < N) { | ||
// file is empty or corrupt | ||
return true; | ||
} | ||
|
||
char buf[N]; | ||
ssize_t bytesLeft = N; | ||
if (lseek(idmap_fd, SEEK_SET, 0) < 0) { | ||
return true; | ||
} | ||
for (;;) { | ||
ssize_t r = TEMP_FAILURE_RETRY(read(idmap_fd, buf + N - bytesLeft, bytesLeft)); | ||
if (r < 0) { | ||
return true; | ||
} | ||
bytesLeft -= r; | ||
if (bytesLeft == 0) { | ||
break; | ||
} | ||
if (r == 0) { | ||
// "shouldn't happen" | ||
return true; | ||
} | ||
} | ||
|
||
uint32_t cached_target_crc, cached_overlay_crc; | ||
String8 cached_target_path, cached_overlay_path; | ||
if (!ResTable::getIdmapInfo(buf, N, &cached_target_crc, &cached_overlay_crc, | ||
&cached_target_path, &cached_overlay_path)) { | ||
return true; | ||
} | ||
|
||
if (cached_target_path != target_apk_path) { | ||
return true; | ||
} | ||
if (cached_overlay_path != overlay_apk_path) { | ||
return true; | ||
} | ||
|
||
uint32_t actual_target_crc, actual_overlay_crc; | ||
if (get_zip_entry_crc(target_apk_path, AssetManager::RESOURCES_FILENAME, | ||
&actual_target_crc) == -1) { | ||
return true; | ||
} | ||
if (get_zip_entry_crc(overlay_apk_path, AssetManager::RESOURCES_FILENAME, | ||
&actual_overlay_crc) == -1) { | ||
return true; | ||
} | ||
|
||
return cached_target_crc != actual_target_crc || cached_overlay_crc != actual_overlay_crc; | ||
} | ||
|
||
bool is_idmap_stale_path(const char *target_apk_path, const char *overlay_apk_path, | ||
const char *idmap_path) | ||
{ | ||
struct stat st; | ||
if (stat(idmap_path, &st) == -1) { | ||
// non-existing idmap is always stale; on other errors, abort idmap generation | ||
return errno == ENOENT; | ||
} | ||
|
||
int idmap_fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY)); | ||
if (idmap_fd == -1) { | ||
return false; | ||
} | ||
bool is_stale = is_idmap_stale_fd(target_apk_path, overlay_apk_path, idmap_fd); | ||
close(idmap_fd); | ||
return is_stale; | ||
} | ||
|
||
int create_idmap(const char *target_apk_path, const char *overlay_apk_path, | ||
uint32_t target_hash, uint32_t overlay_hash, Vector<String8>& targets, | ||
Vector<String8>& overlays, uint32_t **data, size_t *size) | ||
{ | ||
uint32_t target_crc, overlay_crc; | ||
|
||
// In the original implementation, crc of the res tables are generated | ||
// theme apks however do not need a restable, everything is in assets/ | ||
// instead timestamps are used | ||
target_crc = 0; | ||
overlay_crc = 0; | ||
|
||
struct stat statbuf; | ||
|
||
AssetManager am; | ||
bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc, | ||
target_hash, overlay_hash, targets, overlays, data, size); | ||
return b ? 0 : -1; | ||
} | ||
|
||
int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path, | ||
uint32_t target_hash, uint32_t overlay_hash, | ||
const char *redirections, int fd, bool check_if_stale) | ||
{ | ||
if (check_if_stale) { | ||
if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) { | ||
// already up to date -- nothing to do | ||
return 0; | ||
} | ||
} | ||
|
||
Vector<String8> targets; | ||
Vector<String8> overlays; | ||
if (redirections && strlen(redirections)) { | ||
FILE *fp = fopen(redirections, "r"); | ||
char target[280]; | ||
char overlay[280]; | ||
if (fp) { | ||
while (!feof(fp)) { | ||
fscanf(fp, "%279s %279s\n", target, overlay); | ||
targets.push(String8(target)); | ||
overlays.push(String8(overlay)); | ||
} | ||
} | ||
} | ||
|
||
uint32_t *data = NULL; | ||
size_t size; | ||
|
||
if (create_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, | ||
targets, overlays, &data, &size) == -1) { | ||
return -1; | ||
} | ||
|
||
if (write_idmap(fd, data, size) == -1) { | ||
free(data); | ||
return -1; | ||
} | ||
|
||
free(data); | ||
return 0; | ||
} | ||
} | ||
|
||
int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, | ||
uint32_t target_hash, uint32_t overlay_hash, | ||
const char *redirections, const char *idmap_path) | ||
{ | ||
if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) { | ||
// already up to date -- nothing to do | ||
return EXIT_SUCCESS; | ||
} | ||
|
||
int fd = open_idmap(idmap_path); | ||
if (fd == -1) { | ||
return EXIT_FAILURE; | ||
} | ||
|
||
int r = create_and_write_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, | ||
redirections, fd, false); | ||
close(fd); | ||
if (r != 0) { | ||
unlink(idmap_path); | ||
} | ||
return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; | ||
} | ||
|
||
int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, | ||
uint32_t target_hash, uint32_t overlay_hash, | ||
const char *redirections, int fd) | ||
{ | ||
return create_and_write_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, | ||
redirections, fd, true) == 0 ? | ||
EXIT_SUCCESS : EXIT_FAILURE; | ||
} |
Oops, something went wrong.