Skip to content

Commit

Permalink
Merge branch 'cm-11.0' of github.com:CyanogenMod/android_frameworks_n…
Browse files Browse the repository at this point in the history
…ative into HEAD
  • Loading branch information
raymanfx committed Apr 27, 2014
2 parents fe7a405 + ccb5cd9 commit 3892f6d
Show file tree
Hide file tree
Showing 32 changed files with 1,683 additions and 437 deletions.
28 changes: 28 additions & 0 deletions cmds/idmap/Android.mk
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)
243 changes: 243 additions & 0 deletions cmds/idmap/create.cpp
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;
}
Loading

0 comments on commit 3892f6d

Please sign in to comment.