diff options
author | Raphael Moll <ralf@android.com> | 2013-01-04 11:24:13 -0800 |
---|---|---|
committer | Raphael Moll <ralf@android.com> | 2013-01-08 13:59:33 -0800 |
commit | d09956e1e7375d5a6ddd6d2d8c61c96376333d5f (patch) | |
tree | dfed5d7f754235fb95e2e717cfce053177902afa | |
parent | b6049e3c93e27b943832ec300a6d9b04f4f6d474 (diff) | |
download | sdk-d09956e1e7375d5a6ddd6d2d8c61c96376333d5f.zip sdk-d09956e1e7375d5a6ddd6d2d8c61c96376333d5f.tar.gz sdk-d09956e1e7375d5a6ddd6d2d8c61c96376333d5f.tar.bz2 |
SDK: Remove sources for jobb & manifmerge. They are in tools/base now.
Change-Id: I1092079acad333deda47d4c8a092279879fadea6
65 files changed, 0 insertions, 13301 deletions
diff --git a/jobb/etc/Android.mk b/jobb/etc/Android.mk deleted file mode 100644 index 3030e87..0000000 --- a/jobb/etc/Android.mk +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2010 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_PREBUILT_EXECUTABLES := jobb -LOCAL_MODULE_TAGS := debug -include $(BUILD_HOST_PREBUILT) - diff --git a/jobb/etc/jobb b/jobb/etc/jobb deleted file mode 100755 index c782141..0000000 --- a/jobb/etc/jobb +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -# Copyright 2008, 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. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. - -prog="$0" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/`basename "${prog}"` -cd "${oldwd}" - -jarfile=jobb.jar -frameworkdir="$progdir" -libdir="$progdir" -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/tools/lib - libdir=`dirname "$progdir"`/tools/lib -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/framework - libdir=`dirname "$progdir"`/lib -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - echo `basename "$prog"`": can't find $jarfile" - exit 1 -fi - -javaCmd="java" - -if [ `uname` = "Linux" ]; then - export GDK_NATIVE_WINDOWS=true -fi - -jarpath="$frameworkdir/$jarfile:$frameworkdir/fat32lib.jar" - -exec "$javaCmd" \ - $os_opts \ - -classpath "$jarpath" \ - com.android.jobb.Main "$@" - diff --git a/jobb/etc/jobb.bat b/jobb/etc/jobb.bat deleted file mode 100755 index a5043c1..0000000 --- a/jobb/etc/jobb.bat +++ /dev/null @@ -1,51 +0,0 @@ -@echo off
-rem Copyright (C) 2008 The Android Open Source Project
-rem
-rem Licensed under the Apache License, Version 2.0 (the "License");
-rem you may not use this file except in compliance with the License.
-rem You may obtain a copy of the License at
-rem
-rem http://www.apache.org/licenses/LICENSE-2.0
-rem
-rem Unless required by applicable law or agreed to in writing, software
-rem distributed under the License is distributed on an "AS IS" BASIS,
-rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-rem See the License for the specific language governing permissions and
-rem limitations under the License.
-
-rem don't modify the caller's environment
-setlocal
-
-rem Set up prog to be the path of this script, including following symlinks,
-rem and set up progdir to be the fully-qualified pathname of its directory.
-set prog=%~f0
-
-rem Change current directory and drive to where the script is, to avoid
-rem issues with directories containing whitespaces.
-cd /d %~dp0
-
-rem Get the CWD as a full path with short names only (without spaces)
-for %%i in ("%cd%") do set prog_dir=%%~fsi
-
-rem Check we have a valid Java.exe in the path.
-set java_exe=
-call lib\find_java.bat
-if not defined java_exe goto :EOF
-
-set jarfile=jobb.jar
-set frameworkdir=
-set libdir=
-
-if exist %frameworkdir%%jarfile% goto JarFileOk
- set frameworkdir=lib\
-
-if exist %frameworkdir%%jarfile% goto JarFileOk
- set frameworkdir=..\framework\
-
-:JarFileOk
-
-set jarpath=%frameworkdir%%jarfile%;%frameworkdir%libfat32.jar
-
-call %java_exe% %java_debug% -classpath "%jarpath%" com.android.jobb.Main %*
-
-
diff --git a/jobb/etc/manifest.txt b/jobb/etc/manifest.txt deleted file mode 100644 index 305cd61..0000000 --- a/jobb/etc/manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: com.android.jobb.Main -Class-Path: fat32lib.jar diff --git a/jobb/src/Twofish/Twofish_Algorithm.java b/jobb/src/Twofish/Twofish_Algorithm.java deleted file mode 100644 index 330d68e..0000000 --- a/jobb/src/Twofish/Twofish_Algorithm.java +++ /dev/null @@ -1,835 +0,0 @@ -// $Id: $ -// -// $Log: $ -// Revision 1.0 1998/03/24 raif -// + start of history. -// -// $Endlog$ -/* - * Copyright (c) 1997, 1998 Systemics Ltd on behalf of - * the Cryptix Development Team. All rights reserved. - */ -package Twofish; - -import java.io.PrintWriter; -import java.security.InvalidKeyException; - -//........................................................................... -/** - * Twofish is an AES candidate algorithm. It is a balanced 128-bit Feistel - * cipher, consisting of 16 rounds. In each round, a 64-bit S-box value is - * computed from 64 bits of the block, and this value is xored into the other - * half of the block. The two half-blocks are then exchanged, and the next - * round begins. Before the first round, all input bits are xored with key- - * dependent "whitening" subkeys, and after the final round the output bits - * are xored with other key-dependent whitening subkeys; these subkeys are - * not used anywhere else in the algorithm.<p> - * - * Twofish was submitted by Bruce Schneier, Doug Whiting, John Kelsey, Chris - * Hall and David Wagner.<p> - * - * Reference:<ol> - * <li>TWOFISH2.C -- Optimized C API calls for TWOFISH AES submission, - * Version 1.00, April 1998, by Doug Whiting.</ol><p> - * - * <b>Copyright</b> © 1998 - * <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the - * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>. - * <br>All rights reserved.<p> - * - * <b>$Revision: $</b> - * @author Raif S. Naffah - */ -public final class Twofish_Algorithm // implicit no-argument constructor -{ -// Debugging methods and variables -//........................................................................... - - static final String NAME = "Twofish_Algorithm"; - static final boolean IN = true, OUT = false; - - static final boolean DEBUG = Twofish_Properties.GLOBAL_DEBUG; - static final int debuglevel = DEBUG ? Twofish_Properties.getLevel(NAME) : 0; - static final PrintWriter err = DEBUG ? Twofish_Properties.getOutput() : null; - - static final boolean TRACE = Twofish_Properties.isTraceable(NAME); - - static void debug (String s) { err.println(">>> "+NAME+": "+s); } - static void trace (boolean in, String s) { - if (TRACE) err.println((in?"==> ":"<== ")+NAME+"."+s); - } - static void trace (String s) { if (TRACE) err.println("<=> "+NAME+"."+s); } - - -// Constants and variables -//........................................................................... - - static final int BLOCK_SIZE = 16; // bytes in a data-block - private static final int ROUNDS = 16; - private static final int MAX_ROUNDS = 16; // max # rounds (for allocating subkeys) - - /* Subkey array indices */ - private static final int INPUT_WHITEN = 0; - private static final int OUTPUT_WHITEN = INPUT_WHITEN + BLOCK_SIZE/4; - private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + BLOCK_SIZE/4; // 2*(# rounds) - - private static final int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2*MAX_ROUNDS; - - private static final int SK_STEP = 0x02020202; - private static final int SK_BUMP = 0x01010101; - private static final int SK_ROTL = 9; - - /** Fixed 8x8 permutation S-boxes */ - private static final byte[][] P = new byte[][] { - { // p0 - (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8, - (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76, - (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78, - (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38, - (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98, - (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C, - (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26, - (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48, - (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30, - (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23, - (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59, - (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82, - (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E, - (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C, - (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE, - (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61, - (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5, - (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B, - (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B, - (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1, - (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45, - (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66, - (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56, - (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7, - (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5, - (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA, - (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF, - (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71, - (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD, - (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8, - (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D, - (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7, - (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED, - (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2, - (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11, - (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90, - (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF, - (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB, - (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B, - (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF, - (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE, - (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B, - (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46, - (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64, - (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F, - (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A, - (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A, - (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A, - (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29, - (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02, - (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17, - (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D, - (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74, - (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72, - (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12, - (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34, - (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68, - (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8, - (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40, - (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4, - (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0, - (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00, - (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42, - (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 - }, - { // p1 - (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4, - (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8, - (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B, - (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B, - (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD, - (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1, - (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B, - (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F, - (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B, - (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D, - (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E, - (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5, - (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14, - (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3, - (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54, - (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51, - (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A, - (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96, - (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10, - (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C, - (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7, - (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70, - (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB, - (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8, - (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF, - (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC, - (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF, - (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2, - (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82, - (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9, - (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97, - (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17, - (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D, - (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3, - (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C, - (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E, - (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F, - (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49, - (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21, - (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9, - (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD, - (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01, - (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F, - (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48, - (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E, - (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19, - (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57, - (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64, - (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE, - (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5, - (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44, - (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69, - (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15, - (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E, - (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34, - (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC, - (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B, - (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB, - (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52, - (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9, - (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4, - (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2, - (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56, - (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 - } - }; - - /** - * Define the fixed p0/p1 permutations used in keyed S-box lookup. - * By changing the following constant definitions, the S-boxes will - * automatically get changed in the Twofish engine. - */ - private static final int P_00 = 1; - private static final int P_01 = 0; - private static final int P_02 = 0; - private static final int P_03 = P_01 ^ 1; - private static final int P_04 = 1; - - private static final int P_10 = 0; - private static final int P_11 = 0; - private static final int P_12 = 1; - private static final int P_13 = P_11 ^ 1; - private static final int P_14 = 0; - - private static final int P_20 = 1; - private static final int P_21 = 1; - private static final int P_22 = 0; - private static final int P_23 = P_21 ^ 1; - private static final int P_24 = 0; - - private static final int P_30 = 0; - private static final int P_31 = 1; - private static final int P_32 = 1; - private static final int P_33 = P_31 ^ 1; - private static final int P_34 = 1; - - /** Primitive polynomial for GF(256) */ - private static final int GF256_FDBK = 0x169; - private static final int GF256_FDBK_2 = 0x169 / 2; - private static final int GF256_FDBK_4 = 0x169 / 4; - - /** MDS matrix */ - private static final int[][] MDS = new int[4][256]; // blank final - - private static final int RS_GF_FDBK = 0x14D; // field generator - - /** data for hexadecimal visualisation. */ - private static final char[] HEX_DIGITS = { - '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' - }; - - -// Static code - to intialise the MDS matrix -//........................................................................... - - static { - long time = System.currentTimeMillis(); - -if (DEBUG && debuglevel > 6) { -System.out.println("Algorithm Name: "+Twofish_Properties.FULL_NAME); -System.out.println("Electronic Codebook (ECB) Mode"); -System.out.println(); -} - // - // precompute the MDS matrix - // - int[] m1 = new int[2]; - int[] mX = new int[2]; - int[] mY = new int[2]; - int i, j; - for (i = 0; i < 256; i++) { - j = P[0][i] & 0xFF; // compute all the matrix elements - m1[0] = j; - mX[0] = Mx_X( j ) & 0xFF; - mY[0] = Mx_Y( j ) & 0xFF; - - j = P[1][i] & 0xFF; - m1[1] = j; - mX[1] = Mx_X( j ) & 0xFF; - mY[1] = Mx_Y( j ) & 0xFF; - - MDS[0][i] = m1[P_00] << 0 | // fill matrix w/ above elements - mX[P_00] << 8 | - mY[P_00] << 16 | - mY[P_00] << 24; - MDS[1][i] = mY[P_10] << 0 | - mY[P_10] << 8 | - mX[P_10] << 16 | - m1[P_10] << 24; - MDS[2][i] = mX[P_20] << 0 | - mY[P_20] << 8 | - m1[P_20] << 16 | - mY[P_20] << 24; - MDS[3][i] = mX[P_30] << 0 | - m1[P_30] << 8 | - mY[P_30] << 16 | - mX[P_30] << 24; - } - - time = System.currentTimeMillis() - time; - -if (DEBUG && debuglevel > 8) { -System.out.println("=========="); -System.out.println(); -System.out.println("Static Data"); -System.out.println(); -System.out.println("MDS[0][]:"); for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(MDS[0][i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("MDS[1][]:"); for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(MDS[1][i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("MDS[2][]:"); for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(MDS[2][i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("MDS[3][]:"); for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(MDS[3][i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("Total initialization time: "+time+" ms."); -System.out.println(); -} - } - - private static final int LFSR1( int x ) { - return (x >> 1) ^ - ((x & 0x01) != 0 ? GF256_FDBK_2 : 0); - } - - private static final int LFSR2( int x ) { - return (x >> 2) ^ - ((x & 0x02) != 0 ? GF256_FDBK_2 : 0) ^ - ((x & 0x01) != 0 ? GF256_FDBK_4 : 0); - } - - private static final int Mx_1( int x ) { return x; } - private static final int Mx_X( int x ) { return x ^ LFSR2(x); } // 5B - private static final int Mx_Y( int x ) { return x ^ LFSR1(x) ^ LFSR2(x); } // EF - - -// Basic API methods -//........................................................................... - - /** - * Expand a user-supplied key material into a session key. - * - * @param key The 64/128/192/256-bit user-key to use. - * @return This cipher's round keys. - * @exception InvalidKeyException If the key is invalid. - */ - public static synchronized Object makeKey (byte[] k) - throws InvalidKeyException { -if (DEBUG) trace(IN, "makeKey("+k+")"); - if (k == null) - throw new InvalidKeyException("Empty key"); - int length = k.length; - if (!(length == 8 || length == 16 || length == 24 || length == 32)) - throw new InvalidKeyException("Incorrect key length"); - -if (DEBUG && debuglevel > 7) { -System.out.println("Intermediate Session Key Values"); -System.out.println(); -System.out.println("Raw="+toString(k)); -System.out.println(); -} - int k64Cnt = length / 8; - int subkeyCnt = ROUND_SUBKEYS + 2*ROUNDS; - int[] k32e = new int[4]; // even 32-bit entities - int[] k32o = new int[4]; // odd 32-bit entities - int[] sBoxKey = new int[4]; - // - // split user key material into even and odd 32-bit entities and - // compute S-box keys using (12, 8) Reed-Solomon code over GF(256) - // - int i, j, offset = 0; - for (i = 0, j = k64Cnt-1; i < 4 && offset < length; i++, j--) { - k32e[i] = (k[offset++] & 0xFF) | - (k[offset++] & 0xFF) << 8 | - (k[offset++] & 0xFF) << 16 | - (k[offset++] & 0xFF) << 24; - k32o[i] = (k[offset++] & 0xFF) | - (k[offset++] & 0xFF) << 8 | - (k[offset++] & 0xFF) << 16 | - (k[offset++] & 0xFF) << 24; - sBoxKey[j] = RS_MDS_Encode( k32e[i], k32o[i] ); // reverse order - } - // compute the round decryption subkeys for PHT. these same subkeys - // will be used in encryption but will be applied in reverse order. - int q, A, B; - int[] subKeys = new int[subkeyCnt]; - for (i = q = 0; i < subkeyCnt/2; i++, q += SK_STEP) { - A = F32( k64Cnt, q , k32e ); // A uses even key entities - B = F32( k64Cnt, q+SK_BUMP, k32o ); // B uses odd key entities - B = B << 8 | B >>> 24; - A += B; - subKeys[2*i ] = A; // combine with a PHT - A += B; - subKeys[2*i + 1] = A << SK_ROTL | A >>> (32-SK_ROTL); - } - // - // fully expand the table for speed - // - int k0 = sBoxKey[0]; - int k1 = sBoxKey[1]; - int k2 = sBoxKey[2]; - int k3 = sBoxKey[3]; - int b0, b1, b2, b3; - int[] sBox = new int[4 * 256]; - for (i = 0; i < 256; i++) { - b0 = b1 = b2 = b3 = i; - switch (k64Cnt & 3) { - case 1: - sBox[ 2*i ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]; - sBox[ 2*i+1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]; - sBox[0x200+2*i ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]; - sBox[0x200+2*i+1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)]; - break; - case 0: // same as 4 - b0 = (P[P_04][b0] & 0xFF) ^ b0(k3); - b1 = (P[P_14][b1] & 0xFF) ^ b1(k3); - b2 = (P[P_24][b2] & 0xFF) ^ b2(k3); - b3 = (P[P_34][b3] & 0xFF) ^ b3(k3); - case 3: - b0 = (P[P_03][b0] & 0xFF) ^ b0(k2); - b1 = (P[P_13][b1] & 0xFF) ^ b1(k2); - b2 = (P[P_23][b2] & 0xFF) ^ b2(k2); - b3 = (P[P_33][b3] & 0xFF) ^ b3(k2); - case 2: // 128-bit keys - sBox[ 2*i ] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)]; - sBox[ 2*i+1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)]; - sBox[0x200+2*i ] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)]; - sBox[0x200+2*i+1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)]; - } - } - - Object sessionKey = new Object[] { sBox, subKeys }; - -if (DEBUG && debuglevel > 7) { -System.out.println("S-box[]:"); -for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(sBox[i*4+j])+", "); System.out.println();} -System.out.println(); -for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(sBox[256+i*4+j])+", "); System.out.println();} -System.out.println(); -for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(sBox[512+i*4+j])+", "); System.out.println();} -System.out.println(); -for(i=0;i<64;i++) { for(j=0;j<4;j++) System.out.print("0x"+intToString(sBox[768+i*4+j])+", "); System.out.println();} -System.out.println(); -System.out.println("User (odd, even) keys --> S-Box keys:"); -for(i=0;i<k64Cnt;i++) { System.out.println("0x"+intToString(k32o[i])+" 0x"+intToString(k32e[i])+" --> 0x"+intToString(sBoxKey[k64Cnt-1-i])); } -System.out.println(); -System.out.println("Round keys:"); -for(i=0;i<ROUND_SUBKEYS + 2*ROUNDS;i+=2) { System.out.println("0x"+intToString(subKeys[i])+" 0x"+intToString(subKeys[i+1])); } -System.out.println(); - -} -if (DEBUG) trace(OUT, "makeKey()"); - return sessionKey; - } - - /** - * Encrypt exactly one block of plaintext. - * - * @param in The plaintext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for encryption. - * @return The ciphertext generated from a plaintext using the session key. - */ - public static byte[] - blockEncrypt (byte[] in, int inOffset, Object sessionKey) { -if (DEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+")"); - Object[] sk = (Object[]) sessionKey; // extract S-box and session key - int[] sBox = (int[]) sk[0]; - int[] sKey = (int[]) sk[1]; - -if (DEBUG && debuglevel > 6) System.out.println("PT="+toString(in, inOffset, BLOCK_SIZE)); - - int x0 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x1 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x2 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x3 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - - x0 ^= sKey[INPUT_WHITEN ]; - x1 ^= sKey[INPUT_WHITEN + 1]; - x2 ^= sKey[INPUT_WHITEN + 2]; - x3 ^= sKey[INPUT_WHITEN + 3]; -if (DEBUG && debuglevel > 6) System.out.println("PTw="+intToString(x0)+intToString(x1)+intToString(x2)+intToString(x3)); - - int t0, t1; - int k = ROUND_SUBKEYS; - for (int R = 0; R < ROUNDS; R += 2) { - t0 = Fe32( sBox, x0, 0 ); - t1 = Fe32( sBox, x1, 3 ); - x2 ^= t0 + t1 + sKey[k++]; - x2 = x2 >>> 1 | x2 << 31; - x3 = x3 << 1 | x3 >>> 31; - x3 ^= t0 + 2*t1 + sKey[k++]; -if (DEBUG && debuglevel > 6) System.out.println("CT"+(R)+"="+intToString(x0)+intToString(x1)+intToString(x2)+intToString(x3)); - - t0 = Fe32( sBox, x2, 0 ); - t1 = Fe32( sBox, x3, 3 ); - x0 ^= t0 + t1 + sKey[k++]; - x0 = x0 >>> 1 | x0 << 31; - x1 = x1 << 1 | x1 >>> 31; - x1 ^= t0 + 2*t1 + sKey[k++]; -if (DEBUG && debuglevel > 6) System.out.println("CT"+(R+1)+"="+intToString(x0)+intToString(x1)+intToString(x2)+intToString(x3)); - } - x2 ^= sKey[OUTPUT_WHITEN ]; - x3 ^= sKey[OUTPUT_WHITEN + 1]; - x0 ^= sKey[OUTPUT_WHITEN + 2]; - x1 ^= sKey[OUTPUT_WHITEN + 3]; -if (DEBUG && debuglevel > 6) System.out.println("CTw="+intToString(x0)+intToString(x1)+intToString(x2)+intToString(x3)); - - byte[] result = new byte[] { - (byte) x2, (byte)(x2 >>> 8), (byte)(x2 >>> 16), (byte)(x2 >>> 24), - (byte) x3, (byte)(x3 >>> 8), (byte)(x3 >>> 16), (byte)(x3 >>> 24), - (byte) x0, (byte)(x0 >>> 8), (byte)(x0 >>> 16), (byte)(x0 >>> 24), - (byte) x1, (byte)(x1 >>> 8), (byte)(x1 >>> 16), (byte)(x1 >>> 24), - }; - -if (DEBUG && debuglevel > 6) { -System.out.println("CT="+toString(result)); -System.out.println(); -} -if (DEBUG) trace(OUT, "blockEncrypt()"); - return result; - } - - /** - * Decrypt exactly one block of ciphertext. - * - * @param in The ciphertext. - * @param inOffset Index of in from which to start considering data. - * @param sessionKey The session key to use for decryption. - * @return The plaintext generated from a ciphertext using the session key. - */ - public static byte[] - blockDecrypt (byte[] in, int inOffset, Object sessionKey) { -if (DEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+")"); - Object[] sk = (Object[]) sessionKey; // extract S-box and session key - int[] sBox = (int[]) sk[0]; - int[] sKey = (int[]) sk[1]; - -if (DEBUG && debuglevel > 6) System.out.println("CT="+toString(in, inOffset, BLOCK_SIZE)); - - int x2 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x3 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x0 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - int x1 = (in[inOffset++] & 0xFF) | - (in[inOffset++] & 0xFF) << 8 | - (in[inOffset++] & 0xFF) << 16 | - (in[inOffset++] & 0xFF) << 24; - - x2 ^= sKey[OUTPUT_WHITEN ]; - x3 ^= sKey[OUTPUT_WHITEN + 1]; - x0 ^= sKey[OUTPUT_WHITEN + 2]; - x1 ^= sKey[OUTPUT_WHITEN + 3]; -if (DEBUG && debuglevel > 6) System.out.println("CTw="+intToString(x2)+intToString(x3)+intToString(x0)+intToString(x1)); - - int k = ROUND_SUBKEYS + 2*ROUNDS - 1; - int t0, t1; - for (int R = 0; R < ROUNDS; R += 2) { - t0 = Fe32( sBox, x2, 0 ); - t1 = Fe32( sBox, x3, 3 ); - x1 ^= t0 + 2*t1 + sKey[k--]; - x1 = x1 >>> 1 | x1 << 31; - x0 = x0 << 1 | x0 >>> 31; - x0 ^= t0 + t1 + sKey[k--]; -if (DEBUG && debuglevel > 6) System.out.println("PT"+(ROUNDS-R)+"="+intToString(x2)+intToString(x3)+intToString(x0)+intToString(x1)); - - t0 = Fe32( sBox, x0, 0 ); - t1 = Fe32( sBox, x1, 3 ); - x3 ^= t0 + 2*t1 + sKey[k--]; - x3 = x3 >>> 1 | x3 << 31; - x2 = x2 << 1 | x2 >>> 31; - x2 ^= t0 + t1 + sKey[k--]; -if (DEBUG && debuglevel > 6) System.out.println("PT"+(ROUNDS-R-1)+"="+intToString(x2)+intToString(x3)+intToString(x0)+intToString(x1)); - } - x0 ^= sKey[INPUT_WHITEN ]; - x1 ^= sKey[INPUT_WHITEN + 1]; - x2 ^= sKey[INPUT_WHITEN + 2]; - x3 ^= sKey[INPUT_WHITEN + 3]; -if (DEBUG && debuglevel > 6) System.out.println("PTw="+intToString(x2)+intToString(x3)+intToString(x0)+intToString(x1)); - - byte[] result = new byte[] { - (byte) x0, (byte)(x0 >>> 8), (byte)(x0 >>> 16), (byte)(x0 >>> 24), - (byte) x1, (byte)(x1 >>> 8), (byte)(x1 >>> 16), (byte)(x1 >>> 24), - (byte) x2, (byte)(x2 >>> 8), (byte)(x2 >>> 16), (byte)(x2 >>> 24), - (byte) x3, (byte)(x3 >>> 8), (byte)(x3 >>> 16), (byte)(x3 >>> 24), - }; - -if (DEBUG && debuglevel > 6) { -System.out.println("PT="+toString(result)); -System.out.println(); -} -if (DEBUG) trace(OUT, "blockDecrypt()"); - return result; - } - - /** A basic symmetric encryption/decryption test. */ - public static boolean self_test() { return self_test(BLOCK_SIZE); } - - -// own methods -//........................................................................... - - private static final int b0( int x ) { return x & 0xFF; } - private static final int b1( int x ) { return (x >>> 8) & 0xFF; } - private static final int b2( int x ) { return (x >>> 16) & 0xFF; } - private static final int b3( int x ) { return (x >>> 24) & 0xFF; } - - /** - * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box - * 32-bit entity from two key material 32-bit entities. - * - * @param k0 1st 32-bit entity. - * @param k1 2nd 32-bit entity. - * @return Remainder polynomial generated using RS code - */ - private static final int RS_MDS_Encode( int k0, int k1) { - int r = k1; - for (int i = 0; i < 4; i++) // shift 1 byte at a time - r = RS_rem( r ); - r ^= k0; - for (int i = 0; i < 4; i++) - r = RS_rem( r ); - return r; - } - - /* - * Reed-Solomon code parameters: (12, 8) reversible code:<p> - * <pre> - * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1 - * </pre> - * where a = primitive root of field generator 0x14D - */ - private static final int RS_rem( int x ) { - int b = (x >>> 24) & 0xFF; - int g2 = ((b << 1) ^ ( (b & 0x80) != 0 ? RS_GF_FDBK : 0 )) & 0xFF; - int g3 = (b >>> 1) ^ ( (b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0 ) ^ g2 ; - int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b; - return result; - } - - private static final int F32( int k64Cnt, int x, int[] k32 ) { - int b0 = b0(x); - int b1 = b1(x); - int b2 = b2(x); - int b3 = b3(x); - int k0 = k32[0]; - int k1 = k32[1]; - int k2 = k32[2]; - int k3 = k32[3]; - - int result = 0; - switch (k64Cnt & 3) { - case 1: - result = - MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)] ^ - MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)] ^ - MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)] ^ - MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)]; - break; - case 0: // same as 4 - b0 = (P[P_04][b0] & 0xFF) ^ b0(k3); - b1 = (P[P_14][b1] & 0xFF) ^ b1(k3); - b2 = (P[P_24][b2] & 0xFF) ^ b2(k3); - b3 = (P[P_34][b3] & 0xFF) ^ b3(k3); - case 3: - b0 = (P[P_03][b0] & 0xFF) ^ b0(k2); - b1 = (P[P_13][b1] & 0xFF) ^ b1(k2); - b2 = (P[P_23][b2] & 0xFF) ^ b2(k2); - b3 = (P[P_33][b3] & 0xFF) ^ b3(k2); - case 2: // 128-bit keys (optimize for this case) - result = - MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)] ^ - MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)] ^ - MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)] ^ - MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)]; - break; - } - return result; - } - - private static final int Fe32( int[] sBox, int x, int R ) { - return sBox[ 2*_b(x, R ) ] ^ - sBox[ 2*_b(x, R+1) + 1] ^ - sBox[0x200 + 2*_b(x, R+2) ] ^ - sBox[0x200 + 2*_b(x, R+3) + 1]; - } - - private static final int _b( int x, int N) { - int result = 0; - switch (N%4) { - case 0: result = b0(x); break; - case 1: result = b1(x); break; - case 2: result = b2(x); break; - case 3: result = b3(x); break; - } - return result; - } - - /** @return The length in bytes of the Algorithm input block. */ - public static int blockSize() { return BLOCK_SIZE; } - - /** A basic symmetric encryption/decryption test for a given key size. */ - private static boolean self_test (int keysize) { -if (DEBUG) trace(IN, "self_test("+keysize+")"); - boolean ok = false; - try { - byte[] kb = new byte[keysize]; - byte[] pt = new byte[BLOCK_SIZE]; - int i; - - for (i = 0; i < keysize; i++) - kb[i] = (byte) i; - for (i = 0; i < BLOCK_SIZE; i++) - pt[i] = (byte) i; - -if (DEBUG && debuglevel > 6) { -System.out.println("=========="); -System.out.println(); -System.out.println("KEYSIZE="+(8*keysize)); -System.out.println("KEY="+toString(kb)); -System.out.println(); -} - Object key = makeKey(kb); - -if (DEBUG && debuglevel > 6) { -System.out.println("Intermediate Ciphertext Values (Encryption)"); -System.out.println(); -} - byte[] ct = blockEncrypt(pt, 0, key); - -if (DEBUG && debuglevel > 6) { -System.out.println("Intermediate Plaintext Values (Decryption)"); -System.out.println(); -} - byte[] cpt = blockDecrypt(ct, 0, key); - - ok = areEqual(pt, cpt); - if (!ok) - throw new RuntimeException("Symmetric operation failed"); - } catch (Exception x) { -if (DEBUG && debuglevel > 0) { - debug("Exception encountered during self-test: " + x.getMessage()); - x.printStackTrace(); -} - } -if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok); -if (DEBUG) trace(OUT, "self_test()"); - return ok; - } - - -// utility static methods (from cryptix.util.core ArrayUtil and Hex classes) -//........................................................................... - - /** @return True iff the arrays have identical contents. */ - private static boolean areEqual (byte[] a, byte[] b) { - int aLength = a.length; - if (aLength != b.length) - return false; - for (int i = 0; i < aLength; i++) - if (a[i] != b[i]) - return false; - return true; - } - - /** - * Returns a string of 8 hexadecimal digits (most significant - * digit first) corresponding to the integer <i>n</i>, which is - * treated as unsigned. - */ - private static String intToString (int n) { - char[] buf = new char[8]; - for (int i = 7; i >= 0; i--) { - buf[i] = HEX_DIGITS[n & 0x0F]; - n >>>= 4; - } - return new String(buf); - } - - /** - * Returns a string of hexadecimal digits from a byte array. Each - * byte is converted to 2 hex symbols. - */ - private static String toString (byte[] ba) { - return toString(ba, 0, ba.length); - } - private static String toString (byte[] ba, int offset, int length) { - char[] buf = new char[length * 2]; - for (int i = offset, j = 0, k; i < offset+length; ) { - k = ba[i++]; - buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; - buf[j++] = HEX_DIGITS[ k & 0x0F]; - } - return new String(buf); - } - - -// main(): use to generate the Intermediate Values KAT -//........................................................................... - - public static void main (String[] args) { - self_test(16); - self_test(24); - self_test(32); - } -}
\ No newline at end of file diff --git a/jobb/src/Twofish/Twofish_Properties.java b/jobb/src/Twofish/Twofish_Properties.java deleted file mode 100644 index 2098c8f..0000000 --- a/jobb/src/Twofish/Twofish_Properties.java +++ /dev/null @@ -1,197 +0,0 @@ -// $Id: $ -// -// $Log: $ -// Revision 1.0 1998/03/24 raif -// + start of history. -// -// $Endlog$ -/* - * Copyright (c) 1997, 1998 Systemics Ltd on behalf of - * the Cryptix Development Team. All rights reserved. - */ -package Twofish; - -import java.io.InputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.util.Enumeration; -import java.util.Properties; - -/** - * This class acts as a central repository for an algorithm specific - * properties. It reads an (algorithm).properties file containing algorithm- - * specific properties. When using the AES-Kit, this (algorithm).properties - * file is located in the (algorithm).jar file produced by the "jarit" batch/ - * script command.<p> - * - * <b>Copyright</b> © 1997, 1998 - * <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the - * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>. - * <br>All rights reserved.<p> - * - * <b>$Revision: $</b> - * @author David Hopwood - * @author Jill Baker - * @author Raif S. Naffah - */ -public class Twofish_Properties // implicit no-argument constructor -{ -// Constants and variables with relevant static code -//........................................................................... - - static final boolean GLOBAL_DEBUG = false; - - static final String ALGORITHM = "Twofish"; - static final double VERSION = 0.2; - static final String FULL_NAME = ALGORITHM + " ver. " + VERSION; - static final String NAME = "Twofish_Properties"; - - static final Properties properties = new Properties(); - - /** Default properties in case .properties file was not found. */ - private static final String[][] DEFAULT_PROPERTIES = { - {"Trace.Twofish_Algorithm", "true"}, - {"Debug.Level.*", "1"}, - {"Debug.Level.Twofish_Algorithm", "9"}, - }; - - static { -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Looking for " + ALGORITHM + " properties"); - String it = ALGORITHM + ".properties"; - InputStream is = Twofish_Properties.class.getResourceAsStream(it); - boolean ok = is != null; - if (ok) - try { - properties.load(is); - is.close(); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Properties file loaded OK..."); - } catch (Exception x) { - ok = false; - } - if (!ok) { -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": WARNING: Unable to load \"" + it + "\" from CLASSPATH."); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Will use default values instead..."); - int n = DEFAULT_PROPERTIES.length; - for (int i = 0; i < n; i++) - properties.put( - DEFAULT_PROPERTIES[i][0], DEFAULT_PROPERTIES[i][1]); -if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Default properties now set..."); - } - } - - -// Properties methods (excluding load and save, which are deliberately not -// supported). -//........................................................................... - - /** Get the value of a property for this algorithm. */ - public static String getProperty (String key) { - return properties.getProperty(key); - } - - /** - * Get the value of a property for this algorithm, or return - * <i>value</i> if the property was not set. - */ - public static String getProperty (String key, String value) { - return properties.getProperty(key, value); - } - - /** List algorithm properties to the PrintStream <i>out</i>. */ - public static void list (PrintStream out) { - list(new PrintWriter(out, true)); - } - - /** List algorithm properties to the PrintWriter <i>out</i>. */ - public static void list (PrintWriter out) { - out.println("#"); - out.println("# ----- Begin "+ALGORITHM+" properties -----"); - out.println("#"); - String key, value; - Enumeration en = properties.propertyNames(); - while (en.hasMoreElements()) { - key = (String) en.nextElement(); - value = getProperty(key); - out.println(key + " = " + value); - } - out.println("#"); - out.println("# ----- End "+ALGORITHM+" properties -----"); - } - -// public synchronized void load(InputStream in) throws IOException {} - - public static Enumeration propertyNames() { - return properties.propertyNames(); - } - -// public void save (OutputStream os, String comment) {} - - -// Developer support: Tracing and debugging enquiry methods (package-private) -//........................................................................... - - /** - * Return true if tracing is requested for a given class.<p> - * - * User indicates this by setting the tracing <code>boolean</code> - * property for <i>label</i> in the <code>(algorithm).properties</code> - * file. The property's key is "<code>Trace.<i>label</i></code>".<p> - * - * @param label The name of a class. - * @return True iff a boolean true value is set for a property with - * the key <code>Trace.<i>label</i></code>. - */ - static boolean isTraceable (String label) { - String s = getProperty("Trace." + label); - if (s == null) - return false; - return new Boolean(s).booleanValue(); - } - - /** - * Return the debug level for a given class.<p> - * - * User indicates this by setting the numeric property with key - * "<code>Debug.Level.<i>label</i></code>".<p> - * - * If this property is not set, "<code>Debug.Level.*</code>" is looked up - * next. If neither property is set, or if the first property found is - * not a valid decimal integer, then this method returns 0. - * - * @param label The name of a class. - * @return The required debugging level for the designated class. - */ - static int getLevel (String label) { - String s = getProperty("Debug.Level." + label); - if (s == null) { - s = getProperty("Debug.Level.*"); - if (s == null) - return 0; - } - try { - return Integer.parseInt(s); - } catch (NumberFormatException e) { - return 0; - } - } - - /** - * Return the PrintWriter to which tracing and debugging output is to - * be sent.<p> - * - * User indicates this by setting the property with key <code>Output</code> - * to the literal <code>out</code> or <code>err</code>.<p> - * - * By default or if the set value is not allowed, <code>System.err</code> - * will be used. - */ - static PrintWriter getOutput() { - PrintWriter pw; - String name = getProperty("Output"); - if (name != null && name.equals("out")) - pw = new PrintWriter(System.out, true); - else - pw = new PrintWriter(System.err, true); - return pw; - } -}
\ No newline at end of file diff --git a/jobb/src/com/android/jobb/Base64.java b/jobb/src/com/android/jobb/Base64.java deleted file mode 100644 index 7301763..0000000 --- a/jobb/src/com/android/jobb/Base64.java +++ /dev/null @@ -1,276 +0,0 @@ -/* -Copyright (c) 2000 The Legion Of The Bouncy Castle -(http://www.bouncycastle.org) - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -package com.android.jobb; - -public class Base64 -{ - private static final byte[] encodingTable = - { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', - (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', - (byte)'7', (byte)'8', (byte)'9', - (byte)'+', (byte)'/' - }; - - /** - * encode the input data producing a base 64 encoded byte array. - * - * @return a byte array containing the base 64 encoded data. - */ - public static byte[] encode( - byte[] data) - { - byte[] bytes; - - int modulus = data.length % 3; - if (modulus == 0) - { - bytes = new byte[4 * data.length / 3]; - } - else - { - bytes = new byte[4 * ((data.length / 3) + 1)]; - } - - int dataLength = (data.length - modulus); - int a1, a2, a3; - for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) - { - a1 = data[i] & 0xff; - a2 = data[i + 1] & 0xff; - a3 = data[i + 2] & 0xff; - - bytes[j] = encodingTable[(a1 >>> 2) & 0x3f]; - bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]; - bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]; - bytes[j + 3] = encodingTable[a3 & 0x3f]; - } - - /* - * process the tail end. - */ - int b1, b2, b3; - int d1, d2; - - switch (modulus) - { - case 0: /* nothing left to do */ - break; - case 1: - d1 = data[data.length - 1] & 0xff; - b1 = (d1 >>> 2) & 0x3f; - b2 = (d1 << 4) & 0x3f; - - bytes[bytes.length - 4] = encodingTable[b1]; - bytes[bytes.length - 3] = encodingTable[b2]; - bytes[bytes.length - 2] = (byte)'='; - bytes[bytes.length - 1] = (byte)'='; - break; - case 2: - d1 = data[data.length - 2] & 0xff; - d2 = data[data.length - 1] & 0xff; - - b1 = (d1 >>> 2) & 0x3f; - b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; - b3 = (d2 << 2) & 0x3f; - - bytes[bytes.length - 4] = encodingTable[b1]; - bytes[bytes.length - 3] = encodingTable[b2]; - bytes[bytes.length - 2] = encodingTable[b3]; - bytes[bytes.length - 1] = (byte)'='; - break; - } - - return bytes; - } - - /* - * set up the decoding table. - */ - private static final byte[] decodingTable; - - static - { - decodingTable = new byte[128]; - - for (int i = 'A'; i <= 'Z'; i++) - { - decodingTable[i] = (byte)(i - 'A'); - } - - for (int i = 'a'; i <= 'z'; i++) - { - decodingTable[i] = (byte)(i - 'a' + 26); - } - - for (int i = '0'; i <= '9'; i++) - { - decodingTable[i] = (byte)(i - '0' + 52); - } - - decodingTable['+'] = 62; - decodingTable['/'] = 63; - } - - /** - * decode the base 64 encoded input data. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode( - byte[] data) - { - byte[] bytes; - byte b1, b2, b3, b4; - - if (data[data.length - 2] == '=') - { - bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; - } - else if (data[data.length - 1] == '=') - { - bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; - } - else - { - bytes = new byte[((data.length / 4) * 3)]; - } - - for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) - { - b1 = decodingTable[data[i]]; - b2 = decodingTable[data[i + 1]]; - b3 = decodingTable[data[i + 2]]; - b4 = decodingTable[data[i + 3]]; - - bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[j + 2] = (byte)((b3 << 6) | b4); - } - - if (data[data.length - 2] == '=') - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - - bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); - } - else if (data[data.length - 1] == '=') - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - b3 = decodingTable[data[data.length - 2]]; - - bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); - } - else - { - b1 = decodingTable[data[data.length - 4]]; - b2 = decodingTable[data[data.length - 3]]; - b3 = decodingTable[data[data.length - 2]]; - b4 = decodingTable[data[data.length - 1]]; - - bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); - } - - return bytes; - } - - /** - * decode the base 64 encoded String data. - * - * @return a byte array representing the decoded data. - */ - public static byte[] decode( - String data) - { - byte[] bytes; - byte b1, b2, b3, b4; - - if (data.charAt(data.length() - 2) == '=') - { - bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; - } - else if (data.charAt(data.length() - 1) == '=') - { - bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; - } - else - { - bytes = new byte[((data.length() / 4) * 3)]; - } - - for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) - { - b1 = decodingTable[data.charAt(i)]; - b2 = decodingTable[data.charAt(i + 1)]; - b3 = decodingTable[data.charAt(i + 2)]; - b4 = decodingTable[data.charAt(i + 3)]; - - bytes[j] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[j + 2] = (byte)((b3 << 6) | b4); - } - - if (data.charAt(data.length() - 2) == '=') - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - - bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4)); - } - else if (data.charAt(data.length() - 1) == '=') - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - b3 = decodingTable[data.charAt(data.length() - 2)]; - - bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2)); - } - else - { - b1 = decodingTable[data.charAt(data.length() - 4)]; - b2 = decodingTable[data.charAt(data.length() - 3)]; - b3 = decodingTable[data.charAt(data.length() - 2)]; - b4 = decodingTable[data.charAt(data.length() - 1)]; - - bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4)); - bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2)); - bytes[bytes.length - 1] = (byte)((b3 << 6) | b4); - } - - return bytes; - } -} diff --git a/jobb/src/com/android/jobb/Encoder.java b/jobb/src/com/android/jobb/Encoder.java deleted file mode 100644 index 15c01f4..0000000 --- a/jobb/src/com/android/jobb/Encoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -package com.android.jobb; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * Encode and decode byte arrays (typically from binary to 7-bit ASCII - * encodings). - */ -public interface Encoder -{ - int encode(byte[] data, int off, int length, OutputStream out) throws IOException; - - int decode(byte[] data, int off, int length, OutputStream out) throws IOException; - - int decode(String data, OutputStream out) throws IOException; -} diff --git a/jobb/src/com/android/jobb/EncryptedBlockFile.java b/jobb/src/com/android/jobb/EncryptedBlockFile.java deleted file mode 100644 index deb75c4..0000000 --- a/jobb/src/com/android/jobb/EncryptedBlockFile.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * 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. - */ - -package com.android.jobb; - -import Twofish.Twofish_Algorithm; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.security.InvalidKeyException; -import java.util.Arrays; - -public class EncryptedBlockFile extends RandomAccessFile { - - private final class EncryptedBlockFileChannel extends FileChannel { - final FileChannel mFC; - - protected EncryptedBlockFileChannel(FileChannel wrappedFC) { - super(); - mFC = wrappedFC; - } - - @Override - public void force(boolean metaData) throws IOException { - mFC.force(metaData); - } - - @Override - public FileLock lock(long position, long size, boolean shared) throws IOException { - throw new RuntimeException("Lock not implemented"); - } - - @Override - public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException { - throw new RuntimeException("MappedByteBuffer not implemented"); - } - - @Override - public long position() throws IOException { - return mFC.position(); - } - - @Override - public FileChannel position(long newPosition) throws IOException { - mFC.position(newPosition); - return this; - } - - @Override - public int read(ByteBuffer dst) throws IOException { - long position = position(); - int read = read(dst, position); - if ( read >= 0 ) { - position += read; - position(position); - } - return read; - } - - @Override - public int read(ByteBuffer dest, long position) throws IOException { - boolean isMisaligned; - boolean isPartial; - boolean doubleBuffer; - - int toRead = dest.remaining(); - int targetRead = toRead; - int numSectors = toRead / BYTES_PER_SECTOR; - if ((position + toRead) > length()) - throw new IOException( - "reading past end of device"); - - int alignmentOff; - int firstSector = (int) position / BYTES_PER_SECTOR; - if ( 0 != (alignmentOff = (int)(position % BYTES_PER_SECTOR ))) { - toRead += alignmentOff; - numSectors = toRead/BYTES_PER_SECTOR; - isMisaligned = true; - doubleBuffer = true; - System.out.println("Alignment off reading from sector: " + firstSector); - } else { - isMisaligned = false; - doubleBuffer = false; - alignmentOff = 0; - } - - int partialReadSize; - if ( 0 != (partialReadSize = (int)(toRead % BYTES_PER_SECTOR ))) { - isPartial = true; - doubleBuffer = true; - numSectors = toRead/BYTES_PER_SECTOR + 1; - System.out.println("Partial read from sector: " + firstSector); - } else { - isPartial = false; - } - - ByteBuffer tempDest; - if ( doubleBuffer ) { - tempDest = ByteBuffer.allocate(BYTES_PER_SECTOR); - } else { - tempDest = null; - } - int lastSector = firstSector + numSectors; - if ( isMisaligned ) { - // first sector is misaligned. Read and decrypt into temp dest - readDecryptedSector(firstSector++, tempDest); - tempDest.position(alignmentOff); - // special case -- small sector; - if ( firstSector == lastSector && isPartial ) { - tempDest.limit(partialReadSize); - } - dest.put(tempDest); - } - for ( int i = firstSector; i < lastSector; i++ ) { - if ( firstSector+1 == lastSector && isPartial ) { - readDecryptedSector(i, tempDest); - tempDest.rewind(); - tempDest.limit(partialReadSize); - dest.put(tempDest); - } else { - readDecryptedSector(i, dest); - } - } - return targetRead; - } - - @Override - public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { - throw new RuntimeException("Scattering Channel Read not implemented"); - } - - @Override - public long size() throws IOException { - return mFC.size(); - } - - @Override - public long transferFrom(ReadableByteChannel src, long position, long count) - throws IOException { - throw new RuntimeException("File Channel transfer not implemented"); - } - - @Override - public long transferTo(long position, long count, WritableByteChannel target) - throws IOException { - throw new RuntimeException("File Channel transfer to not implemented"); - } - - @Override - public FileChannel truncate(long size) throws IOException { - mFC.truncate(size); - return this; - } - - @Override - public FileLock tryLock(long position, long size, boolean shared) throws IOException { - return mFC.tryLock(position, size, shared); - } - - @Override - public int write(ByteBuffer src) throws IOException { - long position = position(); - int write = write(src, position); - if ( write >= 0 ) { - position += write; - position(position); - } - return write; - } - - @Override - public int write(ByteBuffer src, long position) throws IOException { - int toWrite = src.remaining(); - int targetWrite = toWrite; - int firstSector = (int) position / BYTES_PER_SECTOR; - int numSectors = toWrite / BYTES_PER_SECTOR; - - boolean fixAccess = false; - long readOffset; - if ( 0 != position % BYTES_PER_SECTOR ) { - long alignmentOff = (position % BYTES_PER_SECTOR); - readOffset = position - alignmentOff; - toWrite += alignmentOff; - numSectors = toWrite/BYTES_PER_SECTOR; - fixAccess = true; - System.out.println("Alignment off writing to sector: " + firstSector); - } else { - readOffset = position; - } - - if ( 0 != toWrite % BYTES_PER_SECTOR ) { - numSectors = toWrite/BYTES_PER_SECTOR + 1; - fixAccess = true; - System.out.println("Partial Sector [" + toWrite % BYTES_PER_SECTOR + "] writing to sector: " + firstSector); - } - - if ( fixAccess ) { - ByteBuffer dest = ByteBuffer.allocate(numSectors * BYTES_PER_SECTOR); - read(dest, readOffset); - int bufOffset = (int)(position - readOffset); - dest.position(bufOffset); - dest.put(src); - - src = dest; - src.rewind(); - } - - int lastSector = firstSector + numSectors; - - for ( int i = firstSector; i < lastSector; i++ ) { - writeEncryptedSector(i, src); - } - return targetWrite; - } - - @Override - public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { - throw new RuntimeException("Scattering Channel Write not implemented"); - } - - @Override - protected void implCloseChannel() throws IOException { - // TODO Auto-generated method stub - - } - - /** - * plain: the initial vector is the 32-bit little-endian version of the - * sector number, padded with zeros if necessary. - */ - private void cryptIVPlainGen(int sector, byte[] out) { - Arrays.fill(out, (byte)0); - out[0] = (byte)(sector & 0xff); - out[1] = (byte)(sector >> 8 & 0xff); - out[2] = (byte)(sector >> 16 & 0xff); - out[3] = (byte)(sector >>> 24); - } - - private void readDecryptedSector(int sector, ByteBuffer dest) throws IOException { - ByteBuffer temp = ByteBuffer.allocate(BYTES_PER_SECTOR); - int toRead = BYTES_PER_SECTOR; - int devOffset = BYTES_PER_SECTOR*sector; - - // number of chained twofish blocks - int blockSize = Twofish_Algorithm.blockSize(); - byte[] bufLast = new byte[blockSize]; - int numBlocks = toRead / blockSize; - - // read unencrypted sector - while (toRead > 0) { - final int read = mFC.read(temp, devOffset); - if (read < 0) - throw new IOException(); - toRead -= read; - devOffset += read; - } - temp.rewind(); - - // set initialization vector - cryptIVPlainGen(sector, bufLast); - - byte[] buf = new byte[blockSize]; - for (int i = 0; i < numBlocks; i++) { - temp.get(buf); - // decrypt with chained blocks --- xor with the previous encrypted block - byte[] decryptBuf = Twofish_Algorithm.blockDecrypt(buf, 0, mKey); - for (int j = 0; j < blockSize; j++) { - decryptBuf[j] ^= bufLast[j]; - } - System.arraycopy(buf, 0, bufLast, 0, blockSize); - dest.put(decryptBuf); - } - } - - private void writeEncryptedSector(int sector, ByteBuffer src) throws IOException { - byte[] sectorBuf = new byte[BYTES_PER_SECTOR]; - int toRead = BYTES_PER_SECTOR; - int devOffset = BYTES_PER_SECTOR*sector; - - // number of chained twofish blocks - int blockSize = Twofish_Algorithm.blockSize(); - byte[] bufLast = new byte[blockSize]; - int numBlocks = toRead / blockSize; - - // fetch unencrypted sector - src.get(sectorBuf); - - // set initialization vector - cryptIVPlainGen(sector, bufLast); - - int pos = 0; - byte[] buf = new byte[blockSize]; - for (int i = 0; i < numBlocks; i++) { - System.arraycopy(sectorBuf, pos, buf, 0, blockSize); - // encrypt with chained blocks --- xor with the previous encrypted block - for (int j = 0; j < blockSize; j++) { - buf[j] ^= bufLast[j]; - } - byte[] encryptBuf = Twofish_Algorithm.blockEncrypt(buf, 0, mKey); - bufLast = encryptBuf; - int toWrite = blockSize; - ByteBuffer encryptBuffer = ByteBuffer.wrap(encryptBuf); - while (toWrite > 0) { - final int written = mFC.write(encryptBuffer, devOffset); - if (written < 0) - throw new IOException(); - toWrite -= written; - devOffset += written; - } - pos += blockSize; - } - } - - - } - - public EncryptedBlockFileChannel getEncryptedFileChannel() { - return mEBFC; - } - - /** - * This will clear the file as well as set the length. It would be easy enough - * to preserve the blocks, but that is not the intention of this class. - */ - @Override - public void setLength(long newLength) throws IOException { - int numsectors = (int)newLength/BYTES_PER_SECTOR; - if ( newLength % BYTES_PER_SECTOR != 0 ) { - throw new IOException("Invalid file size!"); - } - super.setLength(newLength); - // write encrypted empty sectors into the block storage - byte[] byteBuf = new byte[BYTES_PER_SECTOR]; - ByteBuffer buf = ByteBuffer.wrap(byteBuf); - for ( int i = 0; i < numsectors; i++ ) { - buf.rewind(); - mEBFC.write(buf); - } - } - - /** - * The number of bytes per sector for all {@code FileDisk} instances. - */ - public final static int BYTES_PER_SECTOR = 512; - - private final Object mKey; - private final EncryptedBlockFileChannel mEBFC; - - public EncryptedBlockFile(byte[] key, File file, String mode) throws FileNotFoundException, - InvalidKeyException { - super(file, mode); - mEBFC = new EncryptedBlockFileChannel(getChannel()); - if (!file.exists()) - throw new FileNotFoundException(); - - mKey = Twofish_Algorithm.makeKey(key); - } -} diff --git a/jobb/src/com/android/jobb/Main.java b/jobb/src/com/android/jobb/Main.java deleted file mode 100644 index a4ea1fc..0000000 --- a/jobb/src/com/android/jobb/Main.java +++ /dev/null @@ -1,607 +0,0 @@ -/* - * 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. - */ - -package com.android.jobb; - -import de.waldheinz.fs.BlockDevice; -import de.waldheinz.fs.FsDirectory; -import de.waldheinz.fs.FsDirectoryEntry; -import de.waldheinz.fs.FsFile; -import de.waldheinz.fs.fat.BootSector; -import de.waldheinz.fs.fat.Fat; -import de.waldheinz.fs.fat.FatFile; -import de.waldheinz.fs.fat.FatFileSystem; -import de.waldheinz.fs.fat.FatLfnDirectory; -import de.waldheinz.fs.fat.FatLfnDirectoryEntry; -import de.waldheinz.fs.fat.FatType; -import de.waldheinz.fs.fat.FatUtils; -import de.waldheinz.fs.fat.SuperFloppyFormatter; -import de.waldheinz.fs.util.FileDisk; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Iterator; -import java.util.Stack; - -public class Main { - - private static final int BLOCK_SIZE = 512; // MUST BE 512 - - public static void printArgs() { - System.out.println("Jobb -- Create OBB files for use on Android"); - System.out.println(); - System.out.println(" -d <directory> Use <directory> as input/output for OBB files"); - System.out.println(" -k <key> Use <key> as password to encrypt/decrypt OBB file"); - System.out.println(" -o <filename> Write OBB file out to <filename>"); - System.out.println(" -v Verbose mode"); - System.out.println(" -h Help; this usage screen"); - System.out.println(" -pn <package> Package name for OBB file"); - System.out.println(" -pv <version> Package version for OBB file"); - System.out.println(" -ov Set overlay flag"); - System.out.println(" -dump <file> Parse and dump OBB file"); - System.out.println(" -about Notices about this tool"); - System.out.println(); - System.out.println("Example: Dump the contents of the encrypted OBB file to the directory"); - System.out.println(" jobb -dump myfile.obb -d ./mydirectory -k mypassword"); - System.out.println(); - System.out.println("Example: Create an encrypted OBB file by recursing the directory path"); - System.out.println(" jobb -pn package.name -pv 1 -d ./mydirectory -k mypassword"); - } - - static String sDirectory; - static File sDirectoryFile; - static boolean sHasOutputDirectory; - static String sKey; - static String sOutputFile; - static boolean sVerboseMode; - static String sPackageName; - static int sPackageVersion = -1; - static byte[] sSalt; - static boolean sOverlay; - static int sFlags; - static String sInputFile; - static byte[] sFishKey; - - private interface FileProcessor { - void processFile(File f); - - void processDirectory(File f); - - /** - * @param dir - */ - void endDirectory(File dir); - } - - static ByteBuffer sTempBuf = ByteBuffer.allocate(1024*1024); - - static public void dumpDirectory(FsDirectory dir, int tabStop, File curDirectory) throws IOException { - Iterator<FsDirectoryEntry> i = dir.iterator(); - while (i.hasNext()) { - final FsDirectoryEntry e = i.next(); - if (e.isDirectory()) { - for (int idx = 0; idx < tabStop; idx++) - System.out.print(' '); - if (e.getName().equals(".") || e.getName().equals("..")) - continue; - for (int idx = 0; idx < tabStop; idx++) - System.out.print(" "); - System.out.println("[" + e + "]"); - dumpDirectory(e.getDirectory(), tabStop + 1, new File(curDirectory, e.getName())); - } else { - for ( int idx = 0; idx < tabStop; idx++ ) System.out.print(" "); - System.out.println( e ); - if ( sHasOutputDirectory ) { - if ( !curDirectory.exists() ) { - if ( false == curDirectory.mkdirs() ) { - throw new IOException("Unable to create directory: " + curDirectory); - } - } - File curFile = new File(curDirectory, e.getName()); - if ( curFile.exists() ) { - throw new IOException("File exists: " + curFile); - } else { - FsFile f = e.getFile(); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(curFile); - FileChannel outputChannel = fos.getChannel(); - int capacity = sTempBuf.capacity(); - long length = f.getLength(); - for ( long pos = 0; pos < length; pos++ ) { - int readLength = (int)(length-pos > capacity ? capacity : length-pos); - sTempBuf.rewind(); - sTempBuf.limit(readLength); - f.read(pos, sTempBuf); - sTempBuf.rewind(); - while(sTempBuf.remaining() > 0) - outputChannel.write(sTempBuf); - pos += readLength; - } - } finally { - if ( null != fos ) fos.close(); - } - } - } - } - } - } - - /** - * @param args - */ - public static void main(String[] args) { - boolean displayHelp = false; - boolean isEncrypted = false; - try { - for (int i = 0; i < args.length; i++) { - String curArg = args[i]; - if (curArg.equals("-d")) { - sDirectory = args[++i]; - sDirectoryFile = new File(sDirectory); - sHasOutputDirectory = true; - } else if (curArg.equals("-k")) { - isEncrypted = true; - sKey = args[++i]; - } else if (curArg.equals("-o")) { - sOutputFile = args[++i]; - } else if (curArg.equals("-h")) { - displayHelp = true; - } else if (curArg.equals("-v")) { - sVerboseMode = true; - } else if (curArg.equals("-pn")) { - sPackageName = args[++i]; - } else if (curArg.equals("-pv")) { - sPackageVersion = Integer.parseInt(args[++i]); - } else if (curArg.equals("-ov")) { - sFlags |= ObbFile.OBB_OVERLAY; - } else if (curArg.equals("-dump")) { - sInputFile = args[++i]; - } else if (curArg.equals("-salt")) { - // special case --- use same salt - String saltString = args[++i]; - BigInteger bi = new BigInteger(saltString, 16); - sSalt = bi.toByteArray(); - if ( sSalt.length != PBKDF.SALT_LEN ) { - displayHelp = true; - } - } else if (curArg.equals("-about")) { - System.out.println("-------------------------------------------------------------------------------"); - System.out.println("Portions of this code:"); - System.out.println("-------------------------------------------------------------------------------"); - System.out.println("Copyright (c) 2000 The Legion Of The Bouncy Castle"); - System.out.println("(http://www.bouncycastle.org)"); - System.out.println(); - System.out.println("Permission is hereby granted, free of charge, to any person obtaining"); - System.out.println("a copy of this software and associated documentation files (the \"Software\""); - System.out.println("to deal in the Software without restriction, including without limitation"); - System.out.println("the rights to use, copy, modify, merge, publish, distribute, sublicense"); - System.out.println("and/or sell copies of the Software, and to permit persons to whom the Software"); - System.out.println("is furnished to do so, subject to the following conditions:"); - System.out.println(); - System.out.println("The above copyright notice and this permission notice shall be included in all"); - System.out.println("copies or substantial portions of the Software."); - System.out.println("-------------------------------------------------------------------------------"); - System.out.println("Twofish is uncopyrighted and license-free, and was created and analyzed by:"); - System.out.println("Bruce Schneier - John Kelsey - Doug Whiting"); - System.out.println("David Wagner - Chris Hall - Niels Ferguson"); - System.out.println("-------------------------------------------------------------------------------"); - System.out.println("Cryptix General License"); - System.out.println(); - System.out.println("Copyright (c) 1995-2005 The Cryptix Foundation Limited."); - System.out.println("All rights reserved."); - System.out.println(""); - System.out.println("Redistribution and use in source and binary forms, with or without"); - System.out.println("modification, are permitted provided that the following conditions are"); - System.out.println("met:"); - System.out.println(); - System.out.println(" 1. Redistributions of source code must retain the copyright notice,"); - System.out.println(" this list of conditions and the following disclaimer."); - System.out.println(" 2. Redistributions in binary form must reproduce the above copyright"); - System.out.println(" notice, this list of conditions and the following disclaimer in"); - System.out.println(" the documentation and/or other materials provided with the"); - System.out.println(" distribution."); - System.out.println("-------------------------------------------------------------------------------"); - return; - } - } - } catch (ArrayIndexOutOfBoundsException e) { - displayHelp = true; - } - if (null != sInputFile) { - ObbFile obbFile = new ObbFile(); - obbFile.readFrom(sInputFile); - System.out.print("Package Name: "); - System.out.println(obbFile.mPackageName); - System.out.print("Package Version: "); - System.out.println(obbFile.mPackageVersion); - if (0 != (obbFile.mFlags & ObbFile.OBB_SALTED)) { - System.out.print("SALT: "); - BigInteger bi = new BigInteger(obbFile.mSalt); - System.out.println(bi.toString(16)); - System.out.println(); - if ( null == sKey ) { - System.out.println("Encrypted file. Please add password."); - return; - } - try { - sFishKey = PBKDF.getKey(sKey,obbFile.mSalt); - bi = new BigInteger(sFishKey); - System.out.println(bi.toString(16)); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - isEncrypted = true; - } else { - isEncrypted = false; - } - File obbInputFile = new File(sInputFile); - - BlockDevice fd; - try { - if ( isEncrypted ) { - EncryptedBlockFile ebf = new EncryptedBlockFile(sFishKey, obbInputFile, "r"); - fd = new FileDisk(ebf, ebf.getEncryptedFileChannel(), true); - } else { - fd = new FileDisk(obbInputFile, true); - } - final FatFileSystem fatFs = FatFileSystem.read(fd, true); - final BootSector bs = fatFs.getBootSector(); - final FsDirectory rootDir = fatFs.getRoot(); - if (sVerboseMode) { - System.out.print("Filesystem Type: "); - FatType ft = bs.getFatType(); - if (ft == FatType.FAT32) { - System.out.println("FAT32"); - } else if (ft == FatType.FAT16) { - System.out.println("FAT16"); - } else if (ft == FatType.FAT12) { - System.out.println("FAT12"); - } else { - System.out.println("Unknown"); - } - System.out.print(" OEM Name: "); - System.out.println(bs.getOemName()); - System.out.print(" Bytes Per Sector: "); - System.out.println(bs.getBytesPerSector()); - System.out.print("Sectors per cluster: "); - System.out.println(bs.getSectorsPerCluster()); - System.out.print(" Reserved Sectors: "); - System.out.println(bs.getNrReservedSectors()); - System.out.print(" Fats: "); - System.out.println(bs.getNrFats()); - System.out.print(" Root Dir Entries: "); - System.out.println(bs.getRootDirEntryCount()); - System.out.print(" Medium Descriptor: "); - System.out.println(bs.getMediumDescriptor()); - System.out.print(" Sectors: "); - System.out.println(bs.getSectorCount()); - System.out.print(" Sectors Per Fat: "); - System.out.println(bs.getSectorsPerFat()); - System.out.print(" Heads: "); - System.out.println(bs.getNrHeads()); - System.out.print(" Hidden Sectors: "); - System.out.println(bs.getNrHiddenSectors()); - System.out.print(" Fat Offset: "); - System.out.println(FatUtils.getFatOffset(bs, 0)); - System.out.println(" RootDir: " + rootDir); - } - dumpDirectory(rootDir, 0, sDirectoryFile); - } catch (IOException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } - return; - } - boolean printArgs; - if (displayHelp) { - printArgs = true; - } else if ( null == sDirectory ) { - printArgs = true; - System.out.println("A directory to be recursed through [-d directory] is required when creating an OBB filesystem."); - } else if ( null == sOutputFile ) { - printArgs = true; - System.out.println("An output filename [-o outputfile] is required when creating an OBB filesystem."); - } else if ( null == sPackageName ) { - printArgs = true; - System.out.println("A package name [-pn package] is required when creating an OBB filesystem."); - } else if ( -1 == sPackageVersion ) { - printArgs = true; - System.out.println("A package version [-pv package] is required when creating an OBB filesystem."); - } else { - printArgs = false; - } - if (printArgs) { - printArgs(); - } else { - if (null != sKey) { - if ( null == sSalt ) { - sSalt = PBKDF.getRandomSalt(); - } - try { - sFishKey = PBKDF.getKey(sKey, sSalt); - } catch (Exception e) { - e.printStackTrace(); - return; - } - sFlags |= ObbFile.OBB_SALTED; - if (sVerboseMode) { - System.out.println("Crypto: "); - System.out.print("SALT: "); - for (byte b : sSalt) { - int out = b & 0xFF; - System.out.print(Integer.toHexString(out)); - System.out.print(" "); - } - System.out.print("\t"); - System.out.print("KEY: "); - for (byte b : sFishKey) { - int out = b & 0xFF; - System.out.print(Integer.toHexString(out)); - System.out.print(" "); - } - System.out.println(); - } - } - if (sVerboseMode) { - System.out.println("Scanning directory: " + sDirectory); - } - final File f = new File(sDirectory); - - long fileSize = getTotalFileSize(f, 0); - fileSize = getTotalFileSize(f, BLOCK_SIZE*SuperFloppyFormatter.clusterSizeFromSize(fileSize, BLOCK_SIZE)); - if (sVerboseMode) { - System.out.println("Total Files: " + fileSize); - } - long numSectors = fileSize / BLOCK_SIZE; - long clusterSize = SuperFloppyFormatter.clusterSizeFromSize(fileSize, BLOCK_SIZE); - long fatOverhead = 2*numSectors/clusterSize*4; - fatOverhead += clusterSize*BLOCK_SIZE - fatOverhead % (clusterSize*BLOCK_SIZE); - fatOverhead += 2*clusterSize; //start at second cluster - if (sVerboseMode) { - System.out.println("FAT Overhead: " + fatOverhead); - } - long clusterSizeInBytes = clusterSize * BLOCK_SIZE; - long filesystemSize = (( numSectors ) * BLOCK_SIZE + fatOverhead + clusterSizeInBytes -1 ) / clusterSizeInBytes * clusterSizeInBytes; - if (sVerboseMode) { - System.out.println("Filesystem Size: " + filesystemSize); - } - File fsFile = new File(sOutputFile); - if (fsFile.exists()) - fsFile.delete(); - try { - BlockDevice fd; - if ( isEncrypted ) { - try { - EncryptedBlockFile ebf = new EncryptedBlockFile(sFishKey, fsFile, "rw"); - ebf.setLength(filesystemSize); - fd = new FileDisk(ebf, ebf.getEncryptedFileChannel(), false); - } catch (InvalidKeyException e) { - e.printStackTrace(); - return; - } - } else { - fd = FileDisk.create(fsFile, filesystemSize); - } - // fat type set based on device size by SuperFloppyFormatter - final FatFileSystem fs = SuperFloppyFormatter.get(fd).format(); - final String rootPath = f.getAbsolutePath(); - // add the files into the filesystem - processAllFiles(f, new FileProcessor() { - Stack<FatLfnDirectory> mCurDir = new Stack<FatLfnDirectory>(); - - @Override - public void processDirectory(File curFile) { - String directory = curFile.getAbsolutePath().substring(rootPath.length()); - if (sVerboseMode) { - System.out.println("Processing Directory: " + directory + " at cluster " + fs.getFat().getLastFreeCluster()); - } - FatLfnDirectory curDir = fs.getRoot(); - if (directory.length() > 0) { - File tempFile = new File(directory); - Stack<String> pathStack = new Stack<String>(); - do { - pathStack.push(tempFile.getName()); - } while (null != (tempFile = tempFile.getParentFile())); - while (!pathStack.empty()) { - String name = pathStack.pop(); - if (0 == name.length()) - continue; - FatLfnDirectoryEntry entry = curDir.getEntry(name); - if (null != entry) { - if (!entry.isDirectory()) { - throw new RuntimeException( - "File path not FAT compatible - naming conflict!"); - } - } else { - try { - if (sVerboseMode) { - System.out.println("Adding Directory: " + name); - } - entry = curDir.addDirectory(name); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Error adding directory!"); - } - } - try { - curDir = entry.getDirectory(); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Error getting directory"); - } - } - } - mCurDir.push(curDir); - } - - @Override - public void processFile(File curFile) { - FatLfnDirectoryEntry entry; - FatLfnDirectory curDir = mCurDir.peek(); - try { - if (sVerboseMode) { - System.out.println("Adding file: " - + curFile.getAbsolutePath().substring(rootPath.length()) - + " with length " + curFile.length() + " at cluster " + fs.getFat().getLastFreeCluster()); - } - entry = curDir.addFile(curFile.getName()); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Error adding file with name: " - + curFile.getName()); - } - ReadableByteChannel channel = null; - try { - FatFile f = entry.getFile(); - channel = new FileInputStream(curFile).getChannel(); - ByteBuffer buf = ByteBuffer.allocateDirect(1024 * 512); - int numRead = 0; - long offset = 0; - while (true) { - buf.clear(); - numRead = channel.read(buf); - if (numRead < 0) - break; - buf.rewind(); - buf.limit(numRead); - f.write(offset, buf); - offset += numRead; - } - f.flush(); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException("Error getting/writing file with name: " - + curFile.getName()); - } finally { - if (null != channel) - try { - channel.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - @Override - public void endDirectory(File dir) { - mCurDir.pop(); - } - - }); - fs.flush(); - fs.close(); - Fat fat = fs.getFat(); - ObbFile ob = new ObbFile(); - ob.setPackageName(sPackageName); - ob.setPackageVersion(sPackageVersion); - ob.setFlags(sFlags); - if (null != sSalt) { - ob.setSalt(sSalt); - } - ob.writeTo(fsFile); - if (sVerboseMode) { - System.out.println("Success!"); - System.out.println("" + fs.getTotalSpace() + " bytes total"); - System.out.println("" + fs.getFreeSpace() + " bytes free"); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static long getTotalFileSize(File dir, final int clusterSize) { - final long[] mSize = new long[3]; - final boolean calculateSlop = clusterSize > 0; - processAllFiles(dir, new FileProcessor() { - Stack<int[]> mDirLen = new Stack<int[]>(); - - @Override - public void processFile(File f) { - if (sVerboseMode) { - System.out.println("Adding size for file: " + f.getAbsolutePath()); - } - long length = f.length(); - if ( calculateSlop && length > 0 ) { - int[] dirLen = mDirLen.peek(); - long realLength = ((clusterSize-1)+length) / clusterSize*clusterSize; - long slop = realLength-length; - length += slop; - mSize[0] += length; - mSize[1] += slop; - dirLen[0] += f.getName().length()/13+3; - } else { - mSize[0] += length; - } - } - - @Override - public void processDirectory(File f) { - if ( calculateSlop ) { - int[] dirLen = new int[1]; - dirLen[0] += f.getName().length()/13+4; - mDirLen.push(dirLen); - } - } - - @Override - public void endDirectory(File dir) { - if ( calculateSlop ) { - int[] dirLen = mDirLen.pop(); - long lastDirLen = dirLen[0] * 32; - if ( lastDirLen != 0 ) { - long realLength = ((clusterSize-1)+lastDirLen) / clusterSize*clusterSize; - long slop = realLength-lastDirLen; - mSize[0] += lastDirLen + slop; - mSize[1] += slop; - mSize[2] += lastDirLen; - } - } - } - }); - System.out.println("Slop: " + mSize[1] + " Directory Overhead: " + mSize[2] ); - return mSize[0]; - } - - // Process all files and directories under dir - public static void processAllFiles(File dir, FileProcessor fp) { - if (dir.isDirectory()) { - fp.processDirectory(dir); - String[] children = dir.list(); - for (int i = 0; i < children.length; i++) { - processAllFiles(new File(dir, children[i]), fp); - } - fp.endDirectory(dir); - } else { - fp.processFile(dir); - } - } -} diff --git a/jobb/src/com/android/jobb/ObbFile.java b/jobb/src/com/android/jobb/ObbFile.java deleted file mode 100644 index e23785d..0000000 --- a/jobb/src/com/android/jobb/ObbFile.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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. - */ - -package com.android.jobb; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; - -public class ObbFile { - public static final int OBB_OVERLAY = (1 << 0); - public static final int OBB_SALTED = (1 << 1); - - static final int kFooterTagSize = 8; /* last two 32-bit integers */ - - static final int kFooterMinSize = 33; /* 32-bit signature version (4 bytes) - * 32-bit package version (4 bytes) - * 32-bit flags (4 bytes) - * 64-bit salt (8 bytes) - * 32-bit package name size (4 bytes) - * >=1-character package name (1 byte) - * 32-bit footer size (4 bytes) - * 32-bit footer marker (4 bytes) - */ - - static final int kMaxBufSize = 32768; /* Maximum file read buffer */ - - static final long kSignature = 0x01059983; /* ObbFile signature */ - - static final int kSigVersion = 1; /* We only know about signature version 1 */ - - /* offsets in version 1 of the header */ - static final int kPackageVersionOffset = 4; - static final int kFlagsOffset = 8; - static final int kSaltOffset = 12; - static final int kPackageNameLenOffset = 20; - static final int kPackageNameOffset = 24; - - long mPackageVersion = -1, mFlags; - String mPackageName; - byte[] mSalt = new byte[8]; - - public ObbFile() {} - - public boolean readFrom(String filename) - { - File obbFile = new File(filename); - return readFrom(obbFile); - } - - public boolean readFrom(File obbFile) - { - return parseObbFile(obbFile); - } - - static public long get4LE(ByteBuffer buf) { - buf.order(ByteOrder.LITTLE_ENDIAN); - return (buf.getInt() & 0xFFFFFFFFL); - } - - public void setPackageName(String packageName) { - mPackageName = packageName; - } - - public void setSalt(byte[] salt) { - if ( salt.length != mSalt.length ) { - throw new RuntimeException("salt must be " + mSalt.length + " characters in length"); - } - System.arraycopy(salt, 0, mSalt, 0, mSalt.length); - } - - public void setPackageVersion(long packageVersion) { - mPackageVersion = packageVersion; - } - - public void setFlags(long flags) { - mFlags = flags; - } - - public boolean parseObbFile(File obbFile) - { - try { - long fileLength = obbFile.length(); - - if (fileLength < kFooterMinSize) { - throw new RuntimeException("file is only " + fileLength + " (less than " + kFooterMinSize + " minimum)"); - } - - RandomAccessFile raf = new RandomAccessFile(obbFile, "r"); - raf.seek(fileLength - kFooterTagSize); - byte[] footer = new byte[kFooterTagSize]; - raf.readFully(footer); - ByteBuffer footBuf = ByteBuffer.wrap(footer); - footBuf.position(4); - long fileSig = get4LE(footBuf); - if (fileSig != kSignature) { - throw new RuntimeException("footer didn't match magic string (expected 0x" + Long.toHexString(kSignature) + ";got 0x" + - Long.toHexString(fileSig)+ ")"); - } - - footBuf.rewind(); - long footerSize = get4LE(footBuf); - if (footerSize > fileLength - kFooterTagSize - || footerSize > kMaxBufSize) { - throw new RuntimeException("claimed footer size is too large (0x" + Long.toHexString(footerSize) + "; file size is 0x" + - Long.toHexString(fileLength)+ ")"); - } - - if (footerSize < (kFooterMinSize - kFooterTagSize)) { - throw new RuntimeException("claimed footer size is too small (0x" + Long.toHexString(footerSize) + "; minimum size is 0x" + - Long.toHexString(kFooterMinSize - kFooterTagSize)); - } - - long fileOffset = fileLength - footerSize - kFooterTagSize; - raf.seek(fileOffset); - - footer = new byte[(int)footerSize]; - raf.readFully(footer); - footBuf = ByteBuffer.wrap(footer); - - long sigVersion = get4LE(footBuf); - if (sigVersion != kSigVersion) { - throw new RuntimeException("Unsupported ObbFile version " + sigVersion ); - } - - footBuf.position(kPackageVersionOffset); - mPackageVersion = get4LE(footBuf); - footBuf.position(kFlagsOffset); - mFlags = get4LE(footBuf); - - footBuf.position(kSaltOffset); - footBuf.get(mSalt); - footBuf.position(kPackageNameLenOffset); - long packageNameLen = get4LE(footBuf); - if (packageNameLen == 0 - || packageNameLen > (footerSize - kPackageNameOffset)) { - throw new RuntimeException("bad ObbFile package name length (0x" + Long.toHexString(packageNameLen) + - "; 0x" + Long.toHexString(footerSize - kPackageNameOffset) + "possible)"); - } - byte[] packageNameBuf = new byte[(int)packageNameLen]; - footBuf.position(kPackageNameOffset); - footBuf.get(packageNameBuf); - - mPackageName = new String(packageNameBuf); - return true; - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } - - public boolean writeTo(String fileName) - { - File obbFile = new File(fileName); - return writeTo(obbFile); - } - - public boolean writeTo(File obbFile) { - if ( !obbFile.exists() ) - return false; - - try { - - long fileLength = obbFile.length(); - RandomAccessFile raf = new RandomAccessFile(obbFile, "rw"); - raf.seek(fileLength); - - if (null == mPackageName || mPackageVersion == -1) { - throw new RuntimeException("tried to write uninitialized ObbFile data"); - } - - FileChannel fc = raf.getChannel(); - ByteBuffer bbInt = ByteBuffer.allocate(4); - bbInt.order(ByteOrder.LITTLE_ENDIAN); - bbInt.putInt(kSigVersion); - bbInt.rewind(); - fc.write(bbInt); - - bbInt.rewind(); - bbInt.putInt((int)mPackageVersion); - bbInt.rewind(); - fc.write(bbInt); - - bbInt.rewind(); - bbInt.putInt((int)mFlags); - bbInt.rewind(); - fc.write(bbInt); - - raf.write(mSalt); - - bbInt.rewind(); - bbInt.putInt(mPackageName.length()); - bbInt.rewind(); - fc.write(bbInt); - - raf.write(mPackageName.getBytes()); - - bbInt.rewind(); - bbInt.putInt(mPackageName.length()+kPackageNameOffset); - bbInt.rewind(); - fc.write(bbInt); - - bbInt.rewind(); - bbInt.putInt((int)kSignature); - bbInt.rewind(); - fc.write(bbInt); - - raf.close(); - return true; - } catch (IOException e) { - e.printStackTrace(); - } - return false; - } -} diff --git a/jobb/src/com/android/jobb/PBKDF.java b/jobb/src/com/android/jobb/PBKDF.java deleted file mode 100644 index 4893c00..0000000 --- a/jobb/src/com/android/jobb/PBKDF.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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. - */ - -package com.android.jobb; - -import java.io.UnsupportedEncodingException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; - -import javax.crypto.SecretKeyFactory; -import javax.crypto.interfaces.PBEKey; -import javax.crypto.spec.PBEKeySpec; - -public class PBKDF { - public static final int SALT_LEN = 8; - private static final int ROUNDS = 1024; - private static final int KEY_BITS = 128; - - public static byte[] getKey(String password, byte[] saltBytes) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { - PBEKeySpec pwKey = new PBEKeySpec(password.toCharArray(), saltBytes, ROUNDS, KEY_BITS); - SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); - PBEKey pbeKey; - try { - pbeKey = (PBEKey) factory.generateSecret(pwKey); - byte[] pbkdfKey = pbeKey.getEncoded(); - return pbkdfKey; - } catch (InvalidKeySpecException e) { - e.printStackTrace(); - } - return null; - } - - public static byte[] getRandomSalt() { - SecureRandom random = new SecureRandom(); - byte[] saltBytes = new byte[SALT_LEN]; - random.nextBytes(saltBytes); - return saltBytes; - } - -} diff --git a/manifmerger/etc/Android.mk b/manifmerger/etc/Android.mk deleted file mode 100644 index 6b180ab..0000000 --- a/manifmerger/etc/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2011 The Android Open Source Project -# -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_PREBUILT_EXECUTABLES := manifmerger -LOCAL_MODULE_TAGS := optional - -include $(BUILD_HOST_PREBUILT) - diff --git a/manifmerger/etc/manifest.txt b/manifmerger/etc/manifest.txt deleted file mode 100644 index bfc9524..0000000 --- a/manifmerger/etc/manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: com.android.manifestmerger.Main -Class-Path: sdklib.jar diff --git a/manifmerger/etc/manifmerger b/manifmerger/etc/manifmerger deleted file mode 100755 index 1e2c2a7..0000000 --- a/manifmerger/etc/manifmerger +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh -# Copyright 2011, 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. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. -prog="$0" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/`basename "${prog}"` -cd "${oldwd}" - -jarfile=manifmerger.jar -frameworkdir="$progdir" -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/tools/lib -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/framework -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - echo `basename "$prog"`": can't find $jarfile" - exit 1 -fi - - -# Check args. -if [ debug = "$1" ]; then - # add this in for debugging - java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y - shift 1 -else - java_debug= -fi - -java_cmd="java" - -# Mac OS X needs an additional arg, or you get an "illegal thread" complaint. -if [ `uname` = "Darwin" ]; then - os_opts="-XstartOnFirstThread" -else - os_opts= -fi - -if [ `uname` = "Linux" ]; then - export GDK_NATIVE_WINDOWS=true -fi - -if [ "$OSTYPE" = "cygwin" ] ; then - jarpath=`cygpath -w "$frameworkdir/$jarfile"` - progdir=`cygpath -w "$progdir"` -else - jarpath="$frameworkdir/$jarfile" -fi - -# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored -exec "$java_cmd" \ - -Xmx256M $os_opts $java_debug \ - -Dcom.android.manifmergerdir="$progdir" \ - -classpath "$jarpath" \ - com.android.manifestmerger.Main "$@" diff --git a/manifmerger/src/main/java/com/android/manifmerger/ArgvParser.java b/manifmerger/src/main/java/com/android/manifmerger/ArgvParser.java deleted file mode 100755 index 6d22f57..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/ArgvParser.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - -import com.android.sdklib.util.CommandLineParser; -import com.android.utils.ILogger; - -import java.util.List; - - -/** - * Specific command-line flags for the {@link ManifestMerger}. - */ -class ArgvParser extends CommandLineParser { - - /* - * Steps needed to add a new action: - * - Each action is defined as a "verb object" followed by parameters. - * - Either reuse a VERB_ constant or define a new one. - * - Either reuse an OBJECT_ constant or define a new one. - * - Add a new entry to mAction with a one-line help summary. - * - In the constructor, add a define() call for each parameter (either mandatory - * or optional) for the given action. - */ - - public final static String VERB_MERGE = "merge"; //$NON-NLS-1$ - public static final String KEY_OUT = "out"; //$NON-NLS-1$ - public static final String KEY_MAIN = "main"; //$NON-NLS-1$ - public static final String KEY_LIBS = "libs"; //$NON-NLS-1$ - - /** - * Action definitions for ManifestMerger command line. - * <p/> - * This list serves two purposes: first it is used to know which verb/object - * actions are acceptable on the command-line; second it provides a summary - * for each action that is printed in the help. - * <p/> - * Each entry is a string array with: - * <ul> - * <li> the verb. - * <li> an object (use #NO_VERB_OBJECT if there's no object). - * <li> a description. - * <li> an alternate form for the object (e.g. plural). - * </ul> - */ - private final static String[][] ACTIONS = { - - { VERB_MERGE, NO_VERB_OBJECT, - "Merge two or more manifests." }, - - }; - - public ArgvParser(ILogger logger) { - super(logger, ACTIONS); - - // The following defines the parameters of the actions defined in mAction. - - // --- merge manifest --- - - define(Mode.STRING, true, - VERB_MERGE, NO_VERB_OBJECT, "o", KEY_OUT, //$NON-NLS-1$ - "Output path (where to write the merged manifest). Use - for stdout.", null); - - define(Mode.STRING, true, - VERB_MERGE, NO_VERB_OBJECT, "1", KEY_MAIN, //$NON-NLS-1$ - "Path of the main manifest (what to merge *into*)", null); - - define(Mode.STRING_ARRAY, true, - VERB_MERGE, NO_VERB_OBJECT, "2", KEY_LIBS, //$NON-NLS-1$ - "Paths of library manifests to be merged into the main one.", - null); - } - - @Override - public boolean acceptLackOfVerb() { - return true; - } - - // -- some helpers for generic action flags - - /** Helper to retrieve the --out value. */ - public String getParamOut() { - return (String) getValue(null, null, KEY_OUT); - } - - /** Helper to retrieve the --main value. */ - public String getParamMain() { - return (String) getValue(null, null, KEY_MAIN); - } - - /** - * Helper to retrieve the --libs values. - */ - public String[] getParamLibs() { - Object v = getValue(null, null, KEY_LIBS); - if (v instanceof List<?>) { - List<?> a = (List<?>) v; - return a.toArray(new String[a.size()]); - } - return null; - } -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/ICallback.java b/manifmerger/src/main/java/com/android/manifmerger/ICallback.java deleted file mode 100755 index 26ae40d..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/ICallback.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ - -package com.android.manifmerger; - -import com.android.annotations.NonNull; - -/** - * Callback used by the ManifestMerger to query the caller. - */ -public interface ICallback { - - public static final int UNKNOWN_CODENAME = 0; - - /** - * Queries the caller to find the API level for a given provisional API codename, - * as used in the <uses-sdk> {@code minSdkVersion} field. - * - * @param codename A non-null codename string. - * @return The integer API > 0 for the given codename, or {@link #UNKNOWN_CODENAME}. - */ - public int queryCodenameApiLevel(@NonNull String codename); - -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/IMergerLog.java b/manifmerger/src/main/java/com/android/manifmerger/IMergerLog.java deleted file mode 100755 index 5402dd4..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/IMergerLog.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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. - */ - -package com.android.manifmerger; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; - - -/** - * Logger interface for the {@link ManifestMerger}. - */ -public interface IMergerLog { - - /** Severity of the error message. */ - public enum Severity { - /** - * A very low severity information. This does not stop processing. - * Clients might want to have a "not verbose" flag to not display this. - */ - INFO, - /** - * A warning. This does not stop processing. - * */ - WARNING, - /** - * A fatal error. - * The merger does not stop on errors, in an attempt to accumulate as much - * info as possible to return to the user. However in case even one error - * is generated the output should not be used, if any. - */ - ERROR - } - - /** - * Logs an error that occurred at a specific single manifest. - * - * @param severity Whether this is an actual error or a mere warning. - * @param location A file and line location of where the error was detected. - * @param message A message string, suitable for {@link String#format(String, Object...)}. - * @param msgParams The optional parameters for the {@code message} string. - */ - public abstract void error( - @NonNull Severity severity, - @NonNull FileAndLine location, - @NonNull String message, - Object...msgParams); - - /** - * Logs a conflict, that is an error that happens when comparing 2 manifests. - * - * @param severity Whether this is an actual error or a mere warning. - * @param location1 A file and line location of where the error was detected. - * By convention, location1 is generally the main manifest location. - * @param location2 A file and line location of where the error was detected. - * By convention, location2 is generally a library location. - * @param message A message string, suitable for {@link String#format(String, Object...)}. - * @param msgParams The optional parameters for the {@code message} string. - */ - public abstract void conflict( - @NonNull Severity severity, - @NonNull FileAndLine location1, - @NonNull FileAndLine location2, - @NonNull String message, - Object...msgParams); - - /** - * Information about the file and line number where an error ocurred. - */ - public static class FileAndLine { - private final String mFilePath; - private final int mLine; - - /** - * Constructs a new {@link FileAndLine}. - * - * @param filePath The file path. This is typically a file path when the - * merge is initiated via the {@code process(File...)} interface. - * When using the {@code process(Document...)} interface, this will be - * one of the magic constants {@link IMergerLog#LIBRARY} or - * {@link IMergerLog#MAIN_MANIFEST}. When that fails, null is used. - * @param line The line number where the error occurred in the XML file. - * Zero is used when the line number isn't known (e.g. when the error - * happens at the document level rather than on a specific element.) - */ - public FileAndLine(@Nullable String filePath, int line) { - mFilePath = filePath; - mLine = line; - } - - /** - * Returns the file path. - * <p/> - * This is typically a file path when the merge is initiated via the - * {@code process(File...)} interface. - * When using the {@code process(Document...)} interface, this will be - * one of the magic constants {@link IMergerLog#LIBRARY} or - * {@link IMergerLog#MAIN_MANIFEST}. - * When that fails, null is used. - */ - public @Nullable String getFileName() { - return mFilePath; - } - - /** - * Returns the line number where the error occurred in the XML file. - * Zero is used when the line number isn't known (e.g. when the error - * happens at the document level rather than on a specific element.) - */ - public int getLine() { - return mLine; - } - - /** - * Displays the information in the form "file:line". - */ - @Override - public String toString() { - String name = mFilePath; - if (MAIN_MANIFEST.equals(name)) { - name = "main manifest"; // translatable - } else if (LIBRARY.equals(name)) { - name = "library"; // translatable - } else if (name == null) { - name = "(Unknown)"; // translatable - } - if (mLine <= 0) { - return name; - } else { - return name + ':' + mLine; - } - } - } - - /** - * The reference to the "main manifest" used in {@link FileAndLine} when the - * path to the main manifest file isn't known. This happens when the - * {@link ManifestMerger} is called with the {@code process(Document...)} - * interface. - */ - public static final String MAIN_MANIFEST = "@main"; //$NON-NLS-1$ - - /** - * The reference to "a library" used in {@link FileAndLine} when the - * path to the library file isn't known. This happens when the - * {@link ManifestMerger} is called with the {@code process(Document...)} - * interface. - */ - public static final String LIBRARY = "@library"; //$NON-NLS-1$ - -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/Main.java b/manifmerger/src/main/java/com/android/manifmerger/Main.java deleted file mode 100644 index 2a6460e..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/Main.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - -import com.android.utils.ILogger; -import com.android.utils.StdLogger; - -import java.io.File; -import java.util.Map; - -/** - * Command-line entry point of the Manifest Merger. - * The goal of the manifest merger is to merge library manifest into a main application manifest. - * See {@link ManifestMerger} for the exact merging rules. - * <p/> - * The command-line version creates a {@link ManifestMerger} - * which takes file arguments from the command-line and dumps all errors and warnings on the - * stdout/stderr console. - * <p/> - * Usage: <br/> - * {@code $ manifmerger merge --main main_manifest.xml --libs lib1.xml lib2.xml --out result.xml} - * <p/> - * When used as a library, please call {@link ManifestMerger#process(File, File, File[], Map)} - * directly. - */ -public class Main { - - /** Logger object. Use this to print normal output, warnings or errors. Never null. */ - private ILogger mSdkLog; - /** Command line parser. Never null. */ - private ArgvParser mArgvParser; - - public static void main(String[] args) { - new Main().run(args); - } - - /** - * Runs the sdk manager app - */ - private void run(String[] args) { - createLogger(); - - mArgvParser = new ArgvParser(mSdkLog); - mArgvParser.parseArgs(args); - - // Create a new ManifestMerger and call its process method. - // It will take care of validating its own arguments. - ManifestMerger mm = new ManifestMerger(MergerLog.wrapSdkLog(mSdkLog), null); - - String[] libPaths = mArgvParser.getParamLibs(); - File[] libFiles = new File[libPaths.length]; - for (int n = libPaths.length - 1; n >= 0; n--) { - libFiles[n] = new File(libPaths[n]); - } - - boolean ok = mm.process( - new File(mArgvParser.getParamOut()), - new File(mArgvParser.getParamMain()), - libFiles, - null /*injectAttributes*/ - ); - System.exit(ok ? 0 : 1); - } - - /** - * Creates the {@link #mSdkLog} object. - * This logger prints to the attached console. - */ - private void createLogger() { - mSdkLog = new StdLogger(StdLogger.Level.VERBOSE); - } - - /** For testing */ - public void setLogger(ILogger logger) { - mSdkLog = logger; - } - -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/ManifestMerger.java b/manifmerger/src/main/java/com/android/manifmerger/ManifestMerger.java deleted file mode 100755 index 2148c98..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/ManifestMerger.java +++ /dev/null @@ -1,1577 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.manifmerger.IMergerLog.FileAndLine; -import com.android.manifmerger.IMergerLog.Severity; -import com.android.utils.XmlUtils; -import com.android.xml.AndroidXPathFactory; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; - -/** - * Merges a library manifest into a main application manifest. - * <p/> - * To use, create with {@link ManifestMerger#ManifestMerger(IMergerLog, ICallback)} then - * call {@link ManifestMerger#process(File, File, File[], Map)}. - * <p/> - * <pre> Merge operations: - * - root manifest: attributes ignored, warn if defined. - * - application: - * G- {@code @attributes}: most attributes are ignored in libs - * except: application:name if defined, it must match. - * except: application:agentBackup if defined, it must match. - * (these represent class names and we don't want a lib to assume their app or backup - * classes are being used when that will never be the case.) - * C- activity / activity-alias / service / receiver / provider - * => Merge as-is. Error if exists in the destination (same {@code @name}) - * unless the definitions are exactly the same. - * New elements are always merged at the end of the application element. - * => Indicate if there's a dup. - * D- uses-library - * => Merge. OK if already exists same {@code @name}. - * => Merge {@code @required}: true>false. - * C- meta-data - * => Merge as-is. Error if exists in the destination (same {@code @name}) - * unless the definitions are exactly the same. - * New elements are always merged at the end of the application element. - * => Indicate if there's a dup. - * A- instrumentation: - * => Do not merge. ignore the ones from libs. - * C- permission / permission-group / permission-tree: - * => Merge as-is. Error if exists in the destination (same {@code @name}) - * unless the definitions are exactly the same. - * C- uses-permission: - * => Add. OK if already defined. - * E- uses-sdk: - * {@code @minSdkVersion}: error if dest<lib. Never automatically change dest minsdk. - * Codenames are accepted if we can resolve their API level. - * {@code @targetSdkVersion}: warning if dest<lib. - * Never automatically change dest targetsdk. - * {@code @maxSdkVersion}: obsolete, ignored. Not used in comparisons and not merged. - * D- uses-feature with {@code @name}: - * => Merge with same {@code @name} - * => Merge {@code @required}: true>false. - * - Do not merge any {@code @glEsVersion} attribute at this point. - * F- uses-feature with {@code @glEsVersion}: - * => Error if defined in lib+dest with dest<lib. Never automatically change dest. - * B- uses-configuration: - * => There can be many. Error if source defines one that is not an exact match in dest. - * (e.g. right now app must manually define something that matches exactly each lib) - * B- supports-screens / compatible-screens: - * => Do not merge. - * => Error (warn?) if defined in lib and not strictly the same as in dest. - * B- supports-gl-texture: - * => Do not merge. Can have more than one. - * => Error (warn?) if defined in lib and not present as-is in dest. - * - * Strategies: - * A = Ignore, do not merge (no-op). - * B = Do not merge but if defined in both must match equally. - * C = Must not exist in dest or be exactly the same (key is the {@code @name} attribute). - * D = Add new or merge with same key {@code @name}, adjust {@code @required} true>false. - * E, F, G = Custom strategies; see above. - * - * What happens when merging libraries with conflicting information? - * Say for example a main manifest has a minSdkVersion of 3, whereas libraries have - * a minSdkVersion of 4 and 11. We could have 2 point of views: - * - Play it safe: If we have a library with a minSdkVersion of 11, it means this - * library code knows it can't work reliably on a lower API level. So the safest end - * result would be a merged manifest with the highest minSdkVersion of all libraries. - * - Trust the main manifest: When an app declares a given minSdkVersion, it also expects - * to run a given range of devices. If we change the final minSdkVersion, the app won't - * be available on as many devices as the developer might expect. And as a counterpoint - * to issue 1, the app may be careful and not call the library without checking the - * necessary features or APIs are available before hand. - * Both points of views are conflicting. The solution taken here is to be conservative - * and generate an error rather than merge and change a value that might be surprising. - * On the other hand this can be problematic and force a developer to keep the main - * manifest in sync with the libraries ones, in essence reducing the usefulness of the - * automated merge to pure trivial cases. The idea is to just start this way and enhance - * or revisit the mechanism later. - * </pre> - */ -public class ManifestMerger { - - /** Logger object. Never null. */ - private final IMergerLog mLog; - /** An optional callback that the merger can use to query the calling SDK. */ - private final ICallback mCallback; - private XPath mXPath; - private Document mMainDoc; - /** Option to extract the package prefixes from the merged manifest. */ - private boolean mExtractPackagePrefix; - - /** Namespace for Android attributes in an AndroidManifest.xml */ - private static final String NS_URI = SdkConstants.NS_RESOURCES; - /** Prefix for the Android namespace to use in XPath expressions. */ - private static final String NS_PREFIX = AndroidXPathFactory.DEFAULT_NS_PREFIX; - /** Namespace used in XML files for Android Tooling attributes */ - private static final String TOOLS_URI = SdkConstants.TOOLS_URI; - /** The name of the tool:merge attribute, to either override or ignore merges. */ - private static final String MERGE_ATTR = "merge"; //$NON-NLS-1$ - /** tool:merge="override" means to ignore what comes from libraries and only keep the - * version from the main manifest. No conflict can be generated. */ - private static final String MERGE_OVERRIDE = "override"; //$NON-NLS-1$ - /** tool:merge="remove" means to remove a node and prevent merging -- not only is the - * node from the libraries not merged, but the element is removed from the main manifest. */ - private static final String MERGE_REMOVE = "remove"; //$NON-NLS-1$ - - /** - * Sets of element/attribute that need to be treated as class names. - * The attribute name must be the local name for the Android namespace. - * For example "application/name" maps to <application android:name=...>. - */ - private static final String[] sClassAttributes = { - "application/name", - "application/backupAgent", - "activity/name", - "activity-alias/name", - "receiver/name", - "service/name", - "provider/name", - "instrumentation/name" - }; - - /** - * Creates a new {@link ManifestMerger}. - * - * @param log A non-null merger log to capture all warnings, errors and their location. - * @param callback An optional callback that the merger can use to query the calling SDK. - */ - public ManifestMerger(@NonNull IMergerLog log, @Nullable ICallback callback) { - mLog = log; - mCallback = callback; - } - - /** - * Sets whether the manifest merger should extract package prefixes. - * <p/> - * When true, the merged document is revisited and class names attributes - * are shortened when possible, e.g. the package prefix is removed from the - * class name if it matches. - * - * @param extract If true, extract package prefixes. - * @return this, for constructor chaining - */ - public ManifestMerger setExtractPackagePrefix(boolean extract) { - mExtractPackagePrefix = extract; - return this; - } - - /** - * Performs the merge operation. - * <p/> - * This does NOT stop on errors, in an attempt to accumulate as much - * info as possible to return to the user. - * Unless it failed to read the main manifest, a result file will be - * created. However if process() returns false, the file should not - * be used except for debugging purposes. - * - * @param outputFile The output path to generate. Can be the same as the main path. - * @param mainFile The main manifest paths to read. What we merge into. - * @param libraryFiles The library manifest paths to read. Must not be null. - * @param injectAttributes A map of attributes to inject in the form [pseudo-xpath] => value. - * The key is "/manifest/elements...|attribute-ns-uri attribute-local-name", - * for example "/manifest/uses-sdk|http://schemas.android.com/apk/res/android minSdkVersion". - * (note the space separator between the attribute URI and its local name.) - * The elements will be created if they don't exists. Existing attributes will be modified. - * The replacement is done on the main document <em>before</em> merging. - * @return True if the merge was completed, false otherwise. - */ - public boolean process( - File outputFile, - File mainFile, - File[] libraryFiles, - Map<String, String> injectAttributes) { - Document mainDoc = MergerXmlUtils.parseDocument(mainFile, mLog); - if (mainDoc == null) { - return false; - } - - boolean success = process(mainDoc, libraryFiles, injectAttributes); - - if (!MergerXmlUtils.printXmlFile(mainDoc, outputFile, mLog)) { - success = false; - } - return success; - } - - /** - * Performs the merge operation in-place in the given DOM. - * <p/> - * This does NOT stop on errors, in an attempt to accumulate as much - * info as possible to return to the user. - * <p/> - * The method might modify the input XML document in-place for its own processing. - * - * @param mainDoc The document to merge into. Will be modified in-place. - * @param libraryFiles The library manifest paths to read. Must not be null. - * These will be modified in-place. - * @param injectAttributes A map of attributes to inject in the form [pseudo-xpath] => value. - * The key is "/manifest/elements...|attribute-ns-uri attribute-local-name", - * for example "/manifest/uses-sdk|http://schemas.android.com/apk/res/android minSdkVersion". - * (note the space separator between the attribute URI and its local name.) - * The elements will be created if they don't exists. Existing attributes will be modified. - * The replacement is done on the main document <em>before</em> merging. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - public boolean process( - Document mainDoc, - File[] libraryFiles, - Map<String, String> injectAttributes) { - - boolean success = true; - mMainDoc = mainDoc; - MergerXmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); - MergerXmlUtils.injectAttributes(mainDoc, injectAttributes, mLog); - - String prefix = XmlUtils.lookupNamespacePrefix(mainDoc, SdkConstants.NS_RESOURCES); - mXPath = AndroidXPathFactory.newXPath(prefix); - - expandFqcns(mainDoc); - for (File libFile : libraryFiles) { - Document libDoc = MergerXmlUtils.parseDocument(libFile, mLog); - if (libDoc == null || !mergeLibDoc(cleanupToolsAttributes(libDoc))) { - success = false; - } - } - - cleanupToolsAttributes(mainDoc); - - if (mExtractPackagePrefix) { - extractFqcns(mainDoc); - } - - mXPath = null; - mMainDoc = null; - return success; - } - - /** - * Performs the merge operation in-place in the given DOM. - * <p/> - * This does NOT stop on errors, in an attempt to accumulate as much - * info as possible to return to the user. - * <p/> - * The method might modify the input XML documents in-place for its own processing. - * - * @param mainDoc The document to merge into. Will be modified in-place. - * @param libraryDocs The library manifest documents to merge in. Must not be null. - * These will be modified in-place. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - public boolean process(@NonNull Document mainDoc, @NonNull Document... libraryDocs) { - - boolean success = true; - mMainDoc = mainDoc; - MergerXmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); - - String prefix = XmlUtils.lookupNamespacePrefix(mainDoc, SdkConstants.NS_RESOURCES); - mXPath = AndroidXPathFactory.newXPath(prefix); - - expandFqcns(mainDoc); - for (Document libDoc : libraryDocs) { - MergerXmlUtils.decorateDocument(libDoc, IMergerLog.LIBRARY); - if (!mergeLibDoc(cleanupToolsAttributes(libDoc))) { - success = false; - } - } - - cleanupToolsAttributes(mainDoc); - mXPath = null; - mMainDoc = null; - return success; - } - - // -------- - - /** - * Merges the given library manifest into the destination manifest. - * See {@link ManifestMerger} for merge details. - * - * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean mergeLibDoc(Document libDoc) { - - boolean err = false; - - expandFqcns(libDoc); - - // Strategy G (check <application> is compatible) - err |= !checkApplication(libDoc); - - // Strategy B - err |= !doNotMergeCheckEqual("/manifest/uses-configuration", libDoc); //$NON-NLS-1$ - err |= !doNotMergeCheckEqual("/manifest/supports-screens", libDoc); //$NON-NLS-1$ - err |= !doNotMergeCheckEqual("/manifest/compatible-screens", libDoc); //$NON-NLS-1$ - err |= !doNotMergeCheckEqual("/manifest/supports-gl-texture", libDoc); //$NON-NLS-1$ - - boolean skipApplication = hasOverrideOrRemoveTag( - findFirstElement(mMainDoc, "/manifest/application")); //$NON-NLS-1$ - - // Strategy C - if (!skipApplication) { - err |= !mergeNewOrEqual( - "/manifest/application/activity", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/activity-alias", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/service", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/receiver", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/provider", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - } - err |= !mergeNewOrEqual( - "/manifest/permission", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - false); - err |= !mergeNewOrEqual( - "/manifest/permission-group", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - false); - err |= !mergeNewOrEqual( - "/manifest/permission-tree", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - false); - err |= !mergeNewOrEqual( - "/manifest/uses-permission", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - false); - - // Strategy D - if (!skipApplication) { - err |= !mergeAdjustRequired( - "/manifest/application/uses-library", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - "required", //$NON-NLS-1$ - libDoc, - null /*alternateKeyAttr*/); - err |= !mergeNewOrEqual( - "/manifest/application/meta-data", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - } - err |= !mergeAdjustRequired( - "/manifest/uses-feature", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - "required", //$NON-NLS-1$ - libDoc, - "glEsVersion" /*alternateKeyAttr*/); - - // Strategy E - err |= !checkSdkVersion(libDoc); - - // Strategy F - err |= !checkGlEsVersion(libDoc); - - return !err; - } - - /** - * Expand all possible class names attributes in the given document. - * <p/> - * Some manifest attributes represent class names. These can be specified as fully - * qualified class names or use a short notation consisting of just the terminal - * class simple name or a dot followed by a partial class name. Unfortunately this - * makes textual comparison of the attributes impossible. To simplify this, we can - * modify the document to fully expand all these class names. The list of elements - * and attributes to process is listed by {@link #sClassAttributes} and the expansion - * simply consists of appending the manifest' package if defined. - * - * @param doc The document in which to expand potential FQCNs. - */ - private void expandFqcns(Document doc) { - // Find the package attribute of the manifest. - String pkg = null; - Element manifest = findFirstElement(doc, "/manifest"); - if (manifest != null) { - pkg = manifest.getAttribute("package"); - } - - if (pkg == null || pkg.length() == 0) { - // We can't adjust FQCNs if we don't know the root package name. - // It's not a proper manifest if this is missing anyway. - assert manifest != null; - mLog.error(Severity.WARNING, - xmlFileAndLine(manifest), - "Missing 'package' attribute in manifest."); - return; - } - - for (String elementAttr : sClassAttributes) { - String[] names = elementAttr.split("/"); - if (names.length != 2) { - continue; - } - String elemName = names[0]; - String attrName = names[1]; - NodeList elements = doc.getElementsByTagName(elemName); - for (int i = 0; i < elements.getLength(); i++) { - Node elem = elements.item(i); - if (elem instanceof Element) { - Attr attr = ((Element) elem).getAttributeNodeNS(NS_URI, attrName); - if (attr != null) { - String value = attr.getNodeValue(); - - // We know it's a shortened FQCN if it starts with a dot - // or does not contain any dot. - if (value != null && value.length() > 0 && - (value.indexOf('.') == -1 || value.charAt(0) == '.')) { - if (value.charAt(0) == '.') { - value = pkg + value; - } else { - value = pkg + '.' + value; - } - attr.setNodeValue(value); - } - } - } - } - } - } - - /** - * Extracts the fully qualified class names from the manifest and uses the - * prefix notation relative to the manifest package. This basically reverses - * the effects of {@link #expandFqcns(Document)}, though of course it may - * also remove prefixes which were inlined in the original documents. - * - * @param doc the document in which to extract the FQCNs. - */ - private void extractFqcns(Document doc) { - // Find the package attribute of the manifest. - String pkg = null; - Element manifest = findFirstElement(doc, "/manifest"); - if (manifest != null) { - pkg = manifest.getAttribute("package"); - } - - if (pkg == null || pkg.length() == 0) { - return; - } - - int pkgLength = pkg.length(); - for (String elementAttr : sClassAttributes) { - String[] names = elementAttr.split("/"); - if (names.length != 2) { - continue; - } - String elemName = names[0]; - String attrName = names[1]; - NodeList elements = doc.getElementsByTagName(elemName); - for (int i = 0; i < elements.getLength(); i++) { - Node elem = elements.item(i); - if (elem instanceof Element) { - Attr attr = ((Element) elem).getAttributeNodeNS(NS_URI, attrName); - if (attr != null) { - String value = attr.getNodeValue(); - - // We know it's a shortened FQCN if it starts with a dot - // or does not contain any dot. - if (value != null && value.length() > pkgLength && - value.startsWith(pkg) && value.charAt(pkgLength) == '.') { - value = value.substring(pkgLength); - attr.setNodeValue(value); - } - } - } - } - } - } - - /** - * Checks (but does not merge) the application attributes using the following rules: - * <pre> - * - {@code @name}: Ignore if empty. Warning if its expanded FQCN doesn't match the main doc. - * - {@code @backupAgent}: Ignore if empty. Warning if its expanded FQCN doesn't match main doc. - * - All other attributes are ignored. - * </pre> - * The name and backupAgent represent classes and the merger will warn since if a lib has - * these defined they will never be used anyway. - * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean checkApplication(Document libDoc) { - - Element mainApp = findFirstElement(mMainDoc, "/manifest/application"); //$NON-NLS-1$ - Element libApp = findFirstElement(libDoc, "/manifest/application"); //$NON-NLS-1$ - - // A manifest does not necessarily define an application. - // If the lib has none, there's nothing to check for. - if (libApp == null) { - return true; - } - if (hasOverrideOrRemoveTag(mainApp)) { - // Don't check the <application> element since it is tagged with override or remove. - return true; - } - - for (String attrName : new String[] { "name", "backupAgent" }) { - String libValue = getAttributeValue(libApp, attrName); - if (libValue == null || libValue.length() == 0) { - // Nothing to do if the attribute is not defined in the lib. - continue; - } - // The main doc does not have to have an application node. - String mainValue = mainApp == null ? "" : getAttributeValue(mainApp, attrName); - if (!libValue.equals(mainValue)) { - assert mainApp != null; - mLog.conflict(Severity.WARNING, - xmlFileAndLine(mainApp), - xmlFileAndLine(libApp), - mainApp == null ? - "Library has <application android:%1$s='%3$s'> but main manifest has no application element." : - "Main manifest has <application android:%1$s='%2$s'> but library uses %1$s='%3$s'.", - attrName, - mainValue, - libValue); - } - } - - return true; - } - - /** - * Do not merge anything. Instead it checks that the requested elements from the - * given library are all present and equal in the destination and prints a warning - * if it's not the case. - * <p/> - * For example if a library supports a given screen configuration, print a - * warning if the main manifest doesn't indicate the app supports the same configuration. - * We should not merge it since we don't want to silently give the impression an app - * supports a configuration just because it uses a library which does. - * On the other hand we don't want to silently ignore this fact. - * <p/> - * TODO there should be a way to silence this warning. - * The current behavior is certainly arbitrary and needs to be tweaked somehow. - * - * @param path The XPath of the elements to merge from the library. Must not be null. - * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean doNotMergeCheckEqual(String path, Document libDoc) { - - for (Element src : findElements(libDoc, path)) { - - boolean found = false; - - for (Element dest : findElements(mMainDoc, path)) { - if (hasOverrideOrRemoveTag(dest)) { - continue; - } - if (compareElements(dest, src, false, null /*diff*/, null /*keyAttr*/)) { - found = true; - break; - } - } - - if (!found) { - mLog.conflict(Severity.WARNING, - xmlFileAndLine(mMainDoc), - xmlFileAndLine(src), - "%1$s defined in library, missing from main manifest:\n%2$s", - path, - MergerXmlUtils.dump(src, false /*nextSiblings*/)); - } - } - - return true; - } - - /** - * Merges the requested elements from the library in the main document. - * The key attribute name is used to identify the same elements. - * Merged elements must either not exist in the destination or be identical. - * <p/> - * When merging, append to the end of the application element. - * Also merges any preceding whitespace and up to one comment just prior to the merged element. - * - * @param path The XPath of the elements to merge from the library. Must not be null. - * @param keyAttr The Android-namespace attribute used as key to identify similar elements. - * E.g. "name" for "android:name" - * @param libDoc The library document to merge from. Must not be null. - * @param warnDups When true, will print a warning when a library definition is already - * present in the destination and is equal. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean mergeNewOrEqual( - String path, - String keyAttr, - Document libDoc, - boolean warnDups) { - - // The parent of XPath /p1/p2/p3 is /p1/p2. To find it, delete the last "/segment" - int pos = path.lastIndexOf('/'); - assert pos > 1; - String parentPath = path.substring(0, pos); - Element parent = findFirstElement(mMainDoc, parentPath); - assert parent != null; - if (parent == null) { - mLog.error(Severity.ERROR, - xmlFileAndLine(mMainDoc), - "Could not find element %1$s.", - parentPath); - return false; - } - - boolean success = true; - - nextSource: for (Element src : findElements(libDoc, path)) { - String name = getAttributeValue(src, keyAttr); - if (name.length() == 0) { - mLog.error(Severity.ERROR, - xmlFileAndLine(src), - "Undefined '%1$s' attribute in %2$s.", - keyAttr, path); - success = false; - continue; - } - - // Look for the same item in the destination - List<Element> dests = findElements(mMainDoc, path, keyAttr, name); - if (dests.size() > 1) { - // This should not be happening. We'll just use the first one found in this case. - mLog.error(Severity.WARNING, - xmlFileAndLine(dests.get(0)), - "Manifest has more than one %1$s[@%2$s=%3$s] element.", - path, keyAttr, name); - } - boolean doMerge = true; - for (Element dest : dests) { - // Don't try to merge this element since it has tools:merge=override|remove. - if (hasOverrideOrRemoveTag(dest)) { - doMerge = false; - continue; - } - // If there's already a similar node in the destination, check it's identical. - StringBuilder diff = new StringBuilder(); - if (compareElements(dest, src, false, diff, keyAttr)) { - // Same element. Skip. - if (warnDups) { - mLog.conflict(Severity.INFO, - xmlFileAndLine(dest), - xmlFileAndLine(src), - "Skipping identical %1$s[@%2$s=%3$s] element.", - path, keyAttr, name); - } - continue nextSource; - } else { - // Print the diff we got from the comparison. - mLog.conflict(Severity.ERROR, - xmlFileAndLine(dest), - xmlFileAndLine(src), - "Trying to merge incompatible %1$s[@%2$s=%3$s] element:\n%4$s", - path, keyAttr, name, diff.toString()); - success = false; - continue nextSource; - } - } - - if (doMerge) { - // Ready to merge element src. Select which previous siblings to merge. - Node start = selectPreviousSiblings(src); - - insertAtEndOf(parent, start, src); - } - } - - return success; - } - - /** - * Returns the value of the given "android:attribute" in the given element. - * - * @param element The non-null element where to extract the attribute. - * @param attrName The local name of the attribute. - * It must use the {@link #NS_URI} but no prefix should be specified here. - * @return The value of the attribute or a non-null empty string if not found. - */ - private String getAttributeValue(Element element, String attrName) { - Attr attr = element.getAttributeNodeNS(NS_URI, attrName); - String value = attr == null ? "" : attr.getNodeValue(); //$NON-NLS-1$ - return value; - } - - /** - * Merge elements as identified by their key name attribute. - * The element must have an option boolean "required" attribute which can be either "true" or - * "false". Default is true if the attribute is missisng. When merging, a "false" is superseded - * by a "true" (explicit or implicit). - * <p/> - * When merging, this does NOT merge any other attributes than {@code keyAttr} and - * {@code requiredAttr}. - * - * @param path The XPath of the elements to merge from the library. Must not be null. - * @param keyAttr The Android-namespace attribute used as key to identify similar elements. - * E.g. "name" for "android:name" - * @param requiredAttr The name of the Android-namespace boolean attribute that must be merged. - * Typically should be "required". - * @param libDoc The library document to merge from. Must not be null. - * @param alternateKeyAttr When non-null, this is an alternate valid key attribute. If the - * default key attribute is missing, we won't output a warning if the alternate one is - * present. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean mergeAdjustRequired( - String path, - String keyAttr, - String requiredAttr, - Document libDoc, - @Nullable String alternateKeyAttr) { - - // The parent of XPath /p1/p2/p3 is /p1/p2. To find it, delete the last "/segment" - int pos = path.lastIndexOf('/'); - assert pos > 1; - String parentPath = path.substring(0, pos); - Element parent = findFirstElement(mMainDoc, parentPath); - assert parent != null; - if (parent == null) { - mLog.error(Severity.ERROR, - xmlFileAndLine(mMainDoc), - "Could not find element %1$s.", - parentPath); - return false; - } - - boolean success = true; - - for (Element src : findElements(libDoc, path)) { - Attr attr = src.getAttributeNodeNS(NS_URI, keyAttr); - String name = attr == null ? "" : attr.getNodeValue().trim(); //$NON-NLS-1$ - if (name.length() == 0) { - if (alternateKeyAttr != null) { - attr = src.getAttributeNodeNS(NS_URI, alternateKeyAttr); - String s = attr == null ? "" : attr.getNodeValue().trim(); //$NON-NLS-1$ - if (s.length() != 0) { - // This element lacks the keyAttr but has the alternateKeyAttr. Skip it. - continue; - } - } - - mLog.error(Severity.ERROR, - xmlFileAndLine(src), - "Undefined '%1$s' attribute in %2$s.", - keyAttr, path); - success = false; - continue; - } - - // Look for the same item in the destination - List<Element> dests = findElements(mMainDoc, path, keyAttr, name); - if (dests.size() > 1) { - // This should not be happening. We'll just use the first one found in this case. - mLog.error(Severity.WARNING, - xmlFileAndLine(dests.get(0)), - "Manifest has more than one %1$s[@%2$s=%3$s] element.", - path, keyAttr, name); - } - if (dests.size() > 0) { - - attr = src.getAttributeNodeNS(NS_URI, requiredAttr); - String value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ - if (value == null || !(value.equals("true") || value.equals("false"))) { - mLog.error(Severity.WARNING, - xmlFileAndLine(src), - "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.", - requiredAttr, path, keyAttr, name, value); - continue; - } - boolean boolE = Boolean.parseBoolean(value); - - for (Element dest : dests) { - // Don't try to merge this element since it has tools:merge=override|remove. - if (hasOverrideOrRemoveTag(dest)) { - continue; - } - - // Compare the required attributes. - attr = dest.getAttributeNodeNS(NS_URI, requiredAttr); - value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ - if (value == null || !(value.equals("true") || value.equals("false"))) { - mLog.error(Severity.WARNING, - xmlFileAndLine(dest), - "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.", - requiredAttr, path, keyAttr, name, value); - continue; - } - boolean boolD = Boolean.parseBoolean(value); - - if (!boolD && boolE) { - // Required attributes differ: destination is false and source was true - // so we need to change the destination to true. - - // If attribute was already in the destination, change it in place - if (attr != null) { - attr.setNodeValue("true"); //$NON-NLS-1$ - } else { - // Otherwise, do nothing. The destination doesn't have the - // required=true attribute, and true is the default value. - // Consequently not setting is the right thing to do. - - // -- code snippet for reference -- - // If we wanted to create a new attribute, we'd use the code - // below. There's a simpler call to d.setAttributeNS(ns, name, value) - // but experience shows that it would create a new prefix out of the - // blue instead of looking it up. - // - // Attr a=d.getOwnerDocument().createAttributeNS(NS_URI, requiredAttr); - // String prefix = d.lookupPrefix(NS_URI); - // if (prefix != null) { - // a.setPrefix(prefix); - // } - // a.setValue("true"); //$NON-NLS-1$ - // d.setAttributeNodeNS(attr); - } - } - } - } else { - // Destination doesn't exist. We simply merge the source element. - // Select which previous siblings to merge. - Node start = selectPreviousSiblings(src); - - Node node = insertAtEndOf(parent, start, src); - - NamedNodeMap attrs = node.getAttributes(); - if (attrs != null) { - for (int i = 0; i < attrs.getLength(); i++) { - Node a = attrs.item(i); - if (a.getNodeType() == Node.ATTRIBUTE_NODE) { - boolean keep = NS_URI.equals(a.getNamespaceURI()); - if (keep) { - name = a.getLocalName(); - keep = keyAttr.equals(name) || requiredAttr.equals(name); - } - if (!keep) { - attrs.removeNamedItemNS(NS_URI, name); - // Restart the loop from index 0 since there's no - // guarantee on the order of the nodes in the "map". - // This makes it O(n+2n) at most, where n is [2..3] in - // a typical case. - i = -1; - } - } - } - } - } - } - - return success; - } - - - - /** - * Checks (but does not merge) uses-feature glEsVersion attribute using the following rules: - * <pre> - * - Error if defined in lib+dest with dest<lib. - * - Never automatically change dest. - * - Default implied value is 1.0 (0x00010000). - * </pre> - * - * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean checkGlEsVersion(Document libDoc) { - - String parentPath = "/manifest"; //$NON-NLS-1$ - Element parent = findFirstElement(mMainDoc, parentPath); - assert parent != null; - if (parent == null) { - mLog.error(Severity.ERROR, - xmlFileAndLine(mMainDoc), - "Could not find element %1$s.", - parentPath); - return false; - } - - // Find the max glEsVersion on the destination side - String path = "/manifest/uses-feature"; //$NON-NLS-1$ - String keyAttr = "glEsVersion"; //$NON-NLS-1$ - long destGlEsVersion = 0x00010000L; // default minimum is 1.0 - Element destNode = null; - boolean result = true; - for (Element dest : findElements(mMainDoc, path)) { - Attr attr = dest.getAttributeNodeNS(NS_URI, keyAttr); - String value = attr == null ? "" : attr.getNodeValue().trim(); //$NON-NLS-1$ - if (value.length() != 0) { - try { - // Note that the value can be an hex number such as 0x00020001 so we - // need Integer.decode instead of Integer.parseInt. - // Note: Integer.decode cannot handle "ffffffff", see JDK issue 6624867 - // so we just treat the version as a long and test like this, ignoring - // the fact that a value of 0xFFFF/.0xFFFF is probably invalid anyway - // in the context of glEsVersion. - long version = Long.decode(value); - if (version >= destGlEsVersion) { - destGlEsVersion = version; - destNode = dest; - } else if (version < 0x00010000) { - mLog.error(Severity.WARNING, - xmlFileAndLine(dest), - "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.", - value); - } - } catch (NumberFormatException e) { - // Note: NumberFormatException.toString() has no interesting information - // so we don't output it. - mLog.error(Severity.ERROR, - xmlFileAndLine(dest), - "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.", - value); - result = false; - } - } - } - - // If we found at least one valid with no error, use that, otherwise bail out. - if (!result && destNode == null) { - return false; - } - - // Now find the max glEsVersion on the source side. - - long srcGlEsVersion = 0x00010000L; // default minimum is 1.0 - Element srcNode = null; - result = true; - for (Element src : findElements(libDoc, path)) { - Attr attr = src.getAttributeNodeNS(NS_URI, keyAttr); - String value = attr == null ? "" : attr.getNodeValue().trim(); //$NON-NLS-1$ - if (value.length() != 0) { - try { - // See comment on Long.decode above. - long version = Long.decode(value); - if (version >= srcGlEsVersion) { - srcGlEsVersion = version; - srcNode = src; - } else if (version < 0x00010000) { - mLog.error(Severity.WARNING, - xmlFileAndLine(src), - "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.", - value); - } - } catch (NumberFormatException e) { - // Note: NumberFormatException.toString() has no interesting information - // so we don't output it. - mLog.error(Severity.ERROR, - xmlFileAndLine(src), - "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.", - value); - result = false; - } - } - } - - if (srcNode != null && destGlEsVersion < srcGlEsVersion) { - mLog.conflict(Severity.WARNING, - xmlFileAndLine(destNode == null ? mMainDoc : destNode), - xmlFileAndLine(srcNode), - "Main manifest has <uses-feature android:glEsVersion='0x%1$08x'> but library uses glEsVersion='0x%2$08x'%3$s", - destGlEsVersion, - srcGlEsVersion, - destNode != null ? "" : //$NON-NLS-1$ - "\nNote: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000." - ); - result = false; - } - - return result; - } - - /** - * Checks (but does not merge) uses-sdk attributes using the following rules: - * <pre> - * - {@code @minSdkVersion}: error if dest<lib. Never automatically change dest minsdk. - * - {@code @targetSdkVersion}: warning if dest<lib. Never automatically change destination. - * - {@code @maxSdkVersion}: obsolete, ignored. Not used in comparisons and not merged. - * - The API level can be a codename if we have a callback that can convert it to an integer. - * </pre> - * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). - */ - private boolean checkSdkVersion(Document libDoc) { - - boolean result = true; - - Element destUsesSdk = findFirstElement(mMainDoc, "/manifest/uses-sdk"); //$NON-NLS-1$ - - if (hasOverrideOrRemoveTag(destUsesSdk)) { - // Don't try to check this element since it has tools:merge=override|remove. - return true; - } - - Element srcUsesSdk = findFirstElement(libDoc, "/manifest/uses-sdk"); //$NON-NLS-1$ - - AtomicInteger destValue = new AtomicInteger(1); - AtomicInteger srcValue = new AtomicInteger(1); - AtomicBoolean destImplied = new AtomicBoolean(true); - AtomicBoolean srcImplied = new AtomicBoolean(true); - - // Check minSdkVersion - int destMinSdk = 1; - result = extractSdkVersionAttribute( - libDoc, - destUsesSdk, srcUsesSdk, - "min", //$NON-NLS-1$ - destValue, srcValue, - destImplied, srcImplied); - - if (result) { - // Make it an error for an application to use a library with a greater - // minSdkVersion. This means the library code may crash unexpectedly. - // TODO it would be nice to be able to work around this in case the - // user think s/he knows what s/he's doing. - // We could define a simple XML comment flag: <!-- @NoMinSdkVersionMergeError --> - - destMinSdk = destValue.get(); - - if (destMinSdk < srcValue.get()) { - mLog.conflict(Severity.ERROR, - xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), - xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), - "Main manifest has <uses-sdk android:minSdkVersion='%1$d'> but library uses minSdkVersion='%2$d'%3$s", - destMinSdk, - srcValue.get(), - !destImplied.get() ? "" : //$NON-NLS-1$ - "\nNote: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1." - ); - result = false; - } - } - - // Check targetSdkVersion. - - // Note that destValue/srcValue purposely defaults to whatever minSdkVersion was last read - // since that's their definition when missing. - destImplied.set(true); - srcImplied.set(true); - - boolean result2 = extractSdkVersionAttribute( - libDoc, - destUsesSdk, srcUsesSdk, - "target", //$NON-NLS-1$ - destValue, srcValue, - destImplied, srcImplied); - - result &= result2; - if (result2) { - // Make it a warning for an application to use a library with a greater - // targetSdkVersion. - - int destTargetSdk = destImplied.get() ? destMinSdk : destValue.get(); - - if (destTargetSdk < srcValue.get()) { - mLog.conflict(Severity.WARNING, - xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), - xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), - "Main manifest has <uses-sdk android:targetSdkVersion='%1$d'> but library uses targetSdkVersion='%2$d'%3$s", - destTargetSdk, - srcValue.get(), - !destImplied.get() ? "" : //$NON-NLS-1$ - "\nNote: main manifest lacks a <uses-sdk android:targetSdkVersion> declaration, which defaults to value minSdkVersion or 1." - ); - result = false; - } - } - - return result; - } - - /** - * Implementation detail for {@link #checkSdkVersion(Document)}. - * Note that the various atomic out-variables must be preset to their default before - * the call. - * <p/> - * destValue/srcValue will be filled with the integer value of the field, if present - * and a correct number, in which case destImplied/destImplied are also set to true. - * Otherwise the values and the implied variables are left untouched. - */ - private boolean extractSdkVersionAttribute( - Document libDoc, - Element destUsesSdk, - Element srcUsesSdk, - String attr, - AtomicInteger destValue, - AtomicInteger srcValue, - AtomicBoolean destImplied, - AtomicBoolean srcImplied) { - String s = destUsesSdk == null ? "" //$NON-NLS-1$ - : destUsesSdk.getAttributeNS(NS_URI, attr + "SdkVersion"); //$NON-NLS-1$ - - boolean result = true; - assert s != null; - s = s.trim(); - try { - if (s.length() > 0) { - destValue.set(Integer.parseInt(s)); - destImplied.set(false); - } - } catch (NumberFormatException e) { - boolean error = true; - if (mCallback != null) { - // Versions can contain codenames such as "JellyBean". - // We'll accept it only if have a callback that can give us the API level for it. - int apiLevel = mCallback.queryCodenameApiLevel(s); - if (apiLevel > ICallback.UNKNOWN_CODENAME) { - destValue.set(apiLevel); - destImplied.set(false); - error = false; - } - } - if (error) { - // Note: NumberFormatException.toString() has no interesting information - // so we don't output it. - mLog.error(Severity.ERROR, - xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), - "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number or codename.", - attr, - s); - result = false; - } - } - - s = srcUsesSdk == null ? "" //$NON-NLS-1$ - : srcUsesSdk.getAttributeNS(NS_URI, attr + "SdkVersion"); //$NON-NLS-1$ - assert s != null; - s = s.trim(); - try { - if (s.length() > 0) { - srcValue.set(Integer.parseInt(s)); - srcImplied.set(false); - } - } catch (NumberFormatException e) { - boolean error = true; - if (mCallback != null) { - // Versions can contain codenames such as "JellyBean". - // We'll accept it only if have a callback that can give us the API level for it. - int apiLevel = mCallback.queryCodenameApiLevel(s); - if (apiLevel > ICallback.UNKNOWN_CODENAME) { - srcValue.set(apiLevel); - srcImplied.set(false); - error = false; - } - } - if (error) { - mLog.error(Severity.ERROR, - xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), - "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number or codename.", - attr, - s); - result = false; - } - } - - return result; - } - - - // ----- - - - /** - * Given an element E, select which previous siblings we want to merge. - * We want to include any whitespace up to the closing of the previous element. - * We also want to include up preceding comment nodes and their preceding whitespace. - * <p/> - * This may returns either {@code end} or a previous sibling. Never returns null. - */ - @NonNull - private Node selectPreviousSiblings(Node end) { - - Node start = end; - Node prev = start.getPreviousSibling(); - while (prev != null) { - short t = prev.getNodeType(); - if (t == Node.TEXT_NODE) { - String text = prev.getNodeValue(); - if (text == null || text.trim().length() != 0) { - // Not whitespace, we don't want it. - break; - } - } else if (t == Node.COMMENT_NODE) { - // It's a comment. We'll take it. - } else { - // Not a comment node nor a whitespace text. We don't want it. - break; - } - start = prev; - prev = start.getPreviousSibling(); - } - - return start; - } - - /** - * Inserts all siblings from {@code start} to {@code end} at the end - * of the given destination element. - * <p/> - * Implementation detail: this clones the source nodes into the destination. - * - * @param dest The destination at the end of which to insert. Cannot be null. - * @param start The first element to insert. Must not be null. - * @param end The last element to insert (included). Must not be null. - * Must be a direct "next sibling" of the start node. - * Can be equal to the start node to insert just that one node. - * @return The copy of the {@code end} node in the destination document or null - * if no such copy was created and added to the destination. - */ - private Node insertAtEndOf(Element dest, Node start, Node end) { - // Check whether we'll need to adjust URI prefixes - String destPrefix = XmlUtils.lookupNamespacePrefix(mMainDoc, NS_URI); - String srcPrefix = XmlUtils.lookupNamespacePrefix(start.getOwnerDocument(), NS_URI); - boolean needPrefixChange = destPrefix != null && !destPrefix.equals(srcPrefix); - - // First let's figure out the insertion point. - // We want the end of the last 'content' element of the - // destination element and basically we want to insert right - // before the last whitespace of the destination element. - Node target = dest.getLastChild(); - while (target != null) { - if (target.getNodeType() == Node.TEXT_NODE) { - String text = target.getNodeValue(); - if (text == null || text.trim().length() != 0) { - // Not whitespace, insert after. - break; - } - } else { - // Not text. Insert after - break; - } - target = target.getPreviousSibling(); - } - if (target != null) { - target = target.getNextSibling(); - } - - // Destination and start..end must not be part of the same document - // because we try to import below. If they were, it would mess the - // structure. - assert dest.getOwnerDocument() == mMainDoc; - assert dest.getOwnerDocument() != start.getOwnerDocument(); - assert start.getOwnerDocument() == end.getOwnerDocument(); - - while (start != null) { - Node node = mMainDoc.importNode(start, true /*deep*/); - if (needPrefixChange) { - changePrefix(node, srcPrefix, destPrefix); - } - dest.insertBefore(node, target); - - if (start == end) { - return node; - } - start = start.getNextSibling(); - } - return null; - } - - /** - * Changes the namespace prefix of all nodes, recursively. - * - * @param node The node to process, as well as all it's descendants. Can be null. - * @param srcPrefix The prefix to match. - * @param destPrefix The new prefix to replace with. - */ - private void changePrefix(Node node, String srcPrefix, String destPrefix) { - for (; node != null; node = node.getNextSibling()) { - if (srcPrefix.equals(node.getPrefix())) { - node.setPrefix(destPrefix); - } - Node child = node.getFirstChild(); - if (child != null) { - changePrefix(child, srcPrefix, destPrefix); - } - } - } - - /** - * Compares two {@link Element}s recursively. - * They must be identical with the same structure. - * Order should not matter. - * Whitespace and comments are ignored. - * - * @param expected The first element to compare. - * @param actual The second element to compare with. - * @param nextSiblings If true, will also compare the following siblings. - * If false, it will just compare the given node. - * @param diff An optional {@link StringBuilder} where to accumulate a diff output. - * @param keyAttr An optional key attribute to always add to elements when dumping a diff. - * @return True if {@code e1} and {@code e2} are equal. - */ - private boolean compareElements( - @NonNull Node expected, - @NonNull Node actual, - boolean nextSiblings, - @Nullable StringBuilder diff, - @Nullable String keyAttr) { - Map<String, String> nsPrefixE = new HashMap<String, String>(); - Map<String, String> nsPrefixA = new HashMap<String, String>(); - String sE = MergerXmlUtils.printElement(expected, nsPrefixE, ""); //$NON-NLS-1$ - String sA = MergerXmlUtils.printElement(actual, nsPrefixA, ""); //$NON-NLS-1$ - if (sE.equals(sA)) { - return true; - } else { - if (diff != null) { - MergerXmlUtils.printXmlDiff(diff, sE, sA, nsPrefixE, nsPrefixA, NS_URI + ':' + keyAttr); - } - return false; - } - } - - /** - * Finds the first element matching the given XPath expression in the given document. - * - * @param doc The document where to find the expression. - * @param path The XPath expression. It must yield an {@link Element} node type. - * @return The {@link Element} found or null. - */ - @Nullable - private Element findFirstElement( - @NonNull Document doc, - @NonNull String path) { - Node result; - try { - result = (Node) mXPath.evaluate(path, doc, XPathConstants.NODE); - if (result instanceof Element) { - return (Element) result; - } - - if (result != null) { - mLog.error(Severity.ERROR, - xmlFileAndLine(doc), - "Unexpected Node type %s when evaluating %s", //$NON-NLS-1$ - result.getClass().getName(), path); - } - } catch (XPathExpressionException e) { - mLog.error(Severity.ERROR, - xmlFileAndLine(doc), - "XPath error on expr %s: %s", //$NON-NLS-1$ - path, e.toString()); - } - return null; - } - - /** - * Finds zero or more elements matching the given XPath expression in the given document. - * - * @param doc The document where to find the expression. - * @param path The XPath expression. Only {@link Element}s nodes will be returned. - * @return A list of {@link Element} found, possibly empty but never null. - */ - private List<Element> findElements( - @NonNull Document doc, - @NonNull String path) { - return findElements(doc, path, null, null); - } - - - /** - * Finds zero or more elements matching the given XPath expression in the given document. - * <p/> - * Furthermore, the elements must have an attribute matching the given attribute name - * and value if provided. (If you don't need to match an attribute, use the other version.) - * <p/> - * Note that if you provide {@code attrName} as non-null then the {@code attrValue} - * must be non-null too. In this case the XPath expression will be modified to add - * the check by naively appending a "[name='value']" filter. - * - * @param doc The document where to find the expression. - * @param path The XPath expression. Only {@link Element}s nodes will be returned. - * @param attrName The name of the optional attribute to match. Can be null. - * @param attrValue The value of the optional attribute to match. - * Can be null if {@code attrName} is null, otherwise must be non-null. - * @return A list of {@link Element} found, possibly empty but never null. - * - * @see #findElements(Document, String) - */ - private List<Element> findElements( - @NonNull Document doc, - @NonNull String path, - @Nullable String attrName, - @Nullable String attrValue) { - List<Element> elements = new ArrayList<Element>(); - - if (attrName != null) { - assert attrValue != null; - // Generate expression /manifest/application/activity[@android:name='my.fqcn'] - path = String.format("%1$s[@%2$s:%3$s='%4$s']", //$NON-NLS-1$ - path, NS_PREFIX, attrName, attrValue); - } - - try { - NodeList results = (NodeList) mXPath.evaluate(path, doc, XPathConstants.NODESET); - if (results != null && results.getLength() > 0) { - for (int i = 0; i < results.getLength(); i++) { - Node n = results.item(i); - assert n instanceof Element; - if (n instanceof Element) { - elements.add((Element) n); - } else { - mLog.error(Severity.ERROR, - xmlFileAndLine(doc), - "Unexpected Node type %s when evaluating %s", //$NON-NLS-1$ - n.getClass().getName(), path); - } - } - } - - } catch (XPathExpressionException e) { - mLog.error(Severity.ERROR, - xmlFileAndLine(doc), - "XPath error on expr %s: %s", //$NON-NLS-1$ - path, e.toString()); - } - - return elements; - } - - /** - * Returns a new {@link FileAndLine} structure that identifies - * the base filename & line number from which the XML node was parsed. - * <p/> - * When the line number is unknown (e.g. if a {@link Document} instance is given) - * then line number 0 will be used. - * - * @param node The node or document where the error occurs. Must not be null. - * @return A new non-null {@link FileAndLine} combining the file name and line number. - */ - private @NonNull FileAndLine xmlFileAndLine(@NonNull Node node) { - return MergerXmlUtils.xmlFileAndLine(node); - } - - /** - * Checks whether the given element has a tools:merge=override or tools:merge=remove attribute. - * @param node The node to check. - * @return True if the element has a tools:merge=override or tools:merge=remove attribute. - */ - private boolean hasOverrideOrRemoveTag(@Nullable Node node) { - if (node == null || node.getNodeType() != Node.ELEMENT_NODE) { - return false; - } - NamedNodeMap attrs = node.getAttributes(); - Node merge = attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR); - String value = merge == null ? null : merge.getNodeValue(); - return MERGE_OVERRIDE.equals(value) || MERGE_REMOVE.equals(value); - } - - /** - * Cleans up all tools attributes from the given node hierarchy. - * <p/> - * If an element is marked with tools:merge=override, this attribute is removed. - * If an element is marked with tools:merge=remove, the <em>whole</em> element is removed. - * - * @param root The root node to parse and edit, recursively. - */ - private void cleanupToolsAttributes(@Nullable Node root) { - if (root == null) { - return; - } - NamedNodeMap attrs = root.getAttributes(); - if (attrs != null) { - for (int i = attrs.getLength() - 1; i >= 0; i--) { - Node attr = attrs.item(i); - if (SdkConstants.XMLNS_URI.equals(attr.getNamespaceURI()) && - TOOLS_URI.equals(attr.getNodeValue())) { - attrs.removeNamedItem(attr.getNodeName()); - } else if (TOOLS_URI.equals(attr.getNamespaceURI()) && - MERGE_ATTR.equals(attr.getLocalName())) { - attrs.removeNamedItem(attr.getNodeName()); - } - } - assert attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR) == null; - } - - for (Node child = root.getFirstChild(); child != null; ) { - if (child.getNodeType() != Node.ELEMENT_NODE) { - child = child.getNextSibling(); - continue; - } - attrs = child.getAttributes(); - Node merge = attrs == null ? null : attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR); - String value = merge == null ? null : merge.getNodeValue(); - Node sibling = child.getNextSibling(); - if (MERGE_REMOVE.equals(value)) { - // Note: save the previous sibling since removing the child will clear its siblings. - Node prev = child.getPreviousSibling(); - root.removeChild(child); - // If there's some whitespace just before that element, clean it up too. - while (prev != null && prev.getNodeType() == Node.TEXT_NODE) { - if (prev.getNodeValue().trim().length() == 0) { - Node prevPrev = prev.getPreviousSibling(); - root.removeChild(prev); - prev = prevPrev; - } else { - break; - } - } - } else { - cleanupToolsAttributes(child); - } - child = sibling; - } - } - - /** - * @see #cleanupToolsAttributes(Node) - */ - private Document cleanupToolsAttributes(@NonNull Document doc) { - cleanupToolsAttributes(doc.getFirstChild()); - return doc; - } -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/MergerLog.java b/manifmerger/src/main/java/com/android/manifmerger/MergerLog.java deleted file mode 100755 index 446898c..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/MergerLog.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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. - */ - -package com.android.manifmerger; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.utils.ILogger; - - -/** - * Helper to create {@link IMergerLog} instances with specific purposes. - */ -public abstract class MergerLog { - - /** - * Create a new instance of a {@link MergerLog} that prints to an {@link ILogger}. - * - * @param sdkLog A non-null {@link ILogger}. - * @return A new IMergerLog. - */ - public static IMergerLog wrapSdkLog(final @NonNull ILogger sdkLog) { - return new IMergerLog() { - @Override - public void error( - @NonNull Severity severity, - @NonNull FileAndLine location, - @NonNull String message, - Object...msgParams) { - - switch(severity) { - case INFO: - sdkLog.info( - "[%1$s] %2$s", //$NON-NLS-1$ - location, - String.format(message, msgParams)); - break; - case WARNING: - sdkLog.warning( - "[%1$s] %2$s", //$NON-NLS-1$ - location, - String.format(message, msgParams)); - break; - case ERROR: - sdkLog.error(null /*throwable*/, - "[%1$s] %2$s", //$NON-NLS-1$ - location, - String.format(message, msgParams)); - break; - } - } - - @Override - public void conflict(@NonNull Severity severity, - @NonNull FileAndLine location1, - @NonNull FileAndLine location2, - @NonNull String message, - Object...msgParams) { - - switch(severity) { - case INFO: - sdkLog.info( - "[%1$s, %2$s] %3$s", //$NON-NLS-1$ - location1, - location2, - String.format(message, msgParams)); - break; - case WARNING: - sdkLog.warning( - "[%1$s, %2$s] %3$s", //$NON-NLS-1$ - location1, - location2, - String.format(message, msgParams)); - break; - case ERROR: - sdkLog.error(null /*throwable*/, - "[%1$s, %2$s] %3$s", //$NON-NLS-1$ - location1, - location2, - String.format(message, msgParams)); - break; - } - }; - }; - } - - /* - * Creates a new instance of a {@link MergerLog} that wraps another {@link IMergerLog} - * and overrides the {@link FileAndLine} locations with the arguments specified. - * <p/> - * An example of usage would be merging temporary files yet associating the errors - * with the original files. - * - * @param parentLog A non-null IMergerLog to wrap. - * @param filePath1 The file path to override in location1 (for errors and conflicts). - * @param filePath2 An optional file path to override in location2 (for conflicts). - * @return A new IMergerLog. - */ - public static IMergerLog mergerLogOverrideLocation( - final @NonNull IMergerLog parentLog, - final @Nullable String filePath1, - final @Nullable String... filePath2) { - return new IMergerLog() { - @Override - public void error( - @NonNull Severity severity, - @NonNull FileAndLine location, - @NonNull String message, - Object...msgParams) { - - if (filePath1 != null) { - location = new FileAndLine(filePath1, location.getLine()); - } - - parentLog.error(severity, location, message, msgParams); - } - - @Override - public void conflict(@NonNull Severity severity, - @NonNull FileAndLine location1, - @NonNull FileAndLine location2, - @NonNull String message, - Object...msgParams) { - - if (filePath1 != null) { - location1 = new FileAndLine(filePath1, location1.getLine()); - } - - if (filePath2 != null && filePath2.length > 0) { - location2 = new FileAndLine(filePath2[0], location2.getLine()); - } - - parentLog.conflict(severity, location1, location2, message, msgParams); - }; - }; - } - -} diff --git a/manifmerger/src/main/java/com/android/manifmerger/MergerXmlUtils.java b/manifmerger/src/main/java/com/android/manifmerger/MergerXmlUtils.java deleted file mode 100755 index bb60464..0000000 --- a/manifmerger/src/main/java/com/android/manifmerger/MergerXmlUtils.java +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.manifmerger.IMergerLog.FileAndLine; -import com.android.manifmerger.IMergerLog.Severity; -import com.android.utils.ILogger; -import com.android.utils.XmlUtils; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXParseException; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -/** - * A few XML handling utilities. - */ -class MergerXmlUtils { - - private static final String DATA_ORIGIN_FILE = "manif.merger.file"; //$NON-NLS-1$ - private static final String DATA_FILE_NAME = "manif.merger.filename"; //$NON-NLS-1$ - private static final String DATA_LINE_NUMBER = "manif.merger.line#"; //$NON-NLS-1$ - - /** - * Parses the given XML file as a DOM document. - * The parser does not validate the DTD nor any kind of schema. - * It is namespace aware. - * <p/> - * This adds a user tag with the original {@link File} to the returned document. - * You can retrieve this file later by using {@link #extractXmlFilename(Node)}. - * - * @param xmlFile The XML {@link File} to parse. Must not be null. - * @param log An {@link ILogger} for reporting errors. Must not be null. - * @return A new DOM {@link Document}, or null. - */ - @Nullable - static Document parseDocument(@NonNull final File xmlFile, @NonNull final IMergerLog log) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - Reader reader = new BufferedReader(new FileReader(xmlFile)); - InputSource is = new InputSource(reader); - factory.setNamespaceAware(true); - factory.setValidating(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - - // We don't want the default handler which prints errors to stderr. - builder.setErrorHandler(new ErrorHandler() { - @Override - public void warning(SAXParseException e) { - log.error(Severity.WARNING, - new FileAndLine(xmlFile.getAbsolutePath(), 0), - "Warning when parsing: %1$s", - e.toString()); - } - @Override - public void fatalError(SAXParseException e) { - log.error(Severity.ERROR, - new FileAndLine(xmlFile.getAbsolutePath(), 0), - "Fatal error when parsing: %1$s", - xmlFile.getName(), e.toString()); - } - @Override - public void error(SAXParseException e) { - log.error(Severity.ERROR, - new FileAndLine(xmlFile.getAbsolutePath(), 0), - "Error when parsing: %1$s", - e.toString()); - } - }); - - Document doc = builder.parse(is); - doc.setUserData(DATA_ORIGIN_FILE, xmlFile, null /*handler*/); - findLineNumbers(doc, 1); - - return doc; - - } catch (FileNotFoundException e) { - log.error(Severity.ERROR, - new FileAndLine(xmlFile.getAbsolutePath(), 0), - "XML file not found"); - - } catch (Exception e) { - log.error(Severity.ERROR, - new FileAndLine(xmlFile.getAbsolutePath(), 0), - "Failed to parse XML file: %1$s", - e.toString()); - } - - return null; - } - - /** - * Parses the given XML string as a DOM document. - * The parser does not validate the DTD nor any kind of schema. - * It is namespace aware. - * - * @param xml The XML string to parse. Must not be null. - * @param log An {@link ILogger} for reporting errors. Must not be null. - * @return A new DOM {@link Document}, or null. - */ - @Nullable - static Document parseDocument(@NonNull String xml, - @NonNull IMergerLog log, - @NonNull FileAndLine errorContext) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - InputSource is = new InputSource(new StringReader(xml)); - factory.setNamespaceAware(true); - factory.setValidating(false); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - findLineNumbers(doc, 1); - return doc; - } catch (Exception e) { - log.error(Severity.ERROR, errorContext, "Failed to parse XML string"); - } - - return null; - } - - /** - * Decorates the document with the specified file name, which can be - * retrieved later by calling {@link #extractLineNumber(Node)}. - * <p/> - * It also tries to add line number information, with the caveat that the - * current implementation is a gross approximation. - * <p/> - * There is no need to call this after calling one of the {@code parseDocument()} - * methods since they already decorated their own document. - * - * @param doc The document to decorate. - * @param fileName The name to retrieve later for that document. - */ - static void decorateDocument(@NonNull Document doc, @NonNull String fileName) { - doc.setUserData(DATA_FILE_NAME, fileName, null /*handler*/); - findLineNumbers(doc, 1); - } - - /** - * Returns a new {@link FileAndLine} structure that identifies - * the base filename & line number from which the XML node was parsed. - * <p/> - * When the line number is unknown (e.g. if a {@link Document} instance is given) - * then line number 0 will be used. - * - * @param node The node or document where the error occurs. Must not be null. - * @return A new non-null {@link FileAndLine} combining the file name and line number. - */ - @NonNull - static FileAndLine xmlFileAndLine(@NonNull Node node) { - String name = extractXmlFilename(node); - int line = extractLineNumber(node); // 0 in case of error or unknown - return new FileAndLine(name, line); - } - - /** - * Extracts the origin {@link File} that {@link #parseDocument(File, IMergerLog)} - * added to the XML document or the string added by - * - * @param xmlNode Any node from a document returned by {@link #parseDocument(File, IMergerLog)}. - * @return The {@link File} object used to create the document or null. - */ - @Nullable - static String extractXmlFilename(@Nullable Node xmlNode) { - if (xmlNode != null && xmlNode.getNodeType() != Node.DOCUMENT_NODE) { - xmlNode = xmlNode.getOwnerDocument(); - } - if (xmlNode != null) { - Object data = xmlNode.getUserData(DATA_ORIGIN_FILE); - if (data instanceof File) { - return ((File) data).getName(); - } - data = xmlNode.getUserData(DATA_FILE_NAME); - if (data instanceof String) { - return (String) data; - } - } - - return null; - } - - /** - * This is a CRUDE INEXACT HACK to decorate the DOM with some kind of line number - * information for elements. It's inexact because by the time we get the DOM we - * already have lost all the information about whitespace between attributes. - * <p/> - * Also we don't even try to deal with \n vs \r vs \r\n insanity. This only counts - * the \n occurring in text nodes to determine line advances, which is clearly flawed. - * <p/> - * However it's good enough for testing, and we'll replace it by a PositionXmlParser - * once it's moved into com.android.util. - */ - private static int findLineNumbers(Node node, int line) { - for (; node != null; node = node.getNextSibling()) { - node.setUserData(DATA_LINE_NUMBER, Integer.valueOf(line), null /*handler*/); - - if (node.getNodeType() == Node.TEXT_NODE) { - String text = node.getNodeValue(); - if (text.length() > 0) { - for (int pos = 0; (pos = text.indexOf('\n', pos)) != -1; pos++) { - ++line; - } - } - } - - Node child = node.getFirstChild(); - if (child != null) { - line = findLineNumbers(child, line); - } - } - return line; - } - - /** - * Extracts the line number that {@link #findLineNumbers} added to the XML nodes. - * - * @param xmlNode Any node from a document returned by {@link #parseDocument(File, IMergerLog)}. - * @return The line number if found or 0. - */ - static int extractLineNumber(@Nullable Node xmlNode) { - if (xmlNode != null) { - Object data = xmlNode.getUserData(DATA_LINE_NUMBER); - if (data instanceof Integer) { - return ((Integer) data).intValue(); - } - } - - return 0; - } - - /** - * Outputs the given XML {@link Document} to the file {@code outFile}. - * - * TODO right now reformats the document. Needs to output as-is, respecting white-space. - * - * @param doc The document to output. Must not be null. - * @param outFile The {@link File} where to write the document. - * @param log A log in case of error. - * @return True if the file was written, false in case of error. - */ - static boolean printXmlFile( - @NonNull Document doc, - @NonNull File outFile, - @NonNull IMergerLog log) { - // Quick thing based on comments from http://stackoverflow.com/questions/139076 - try { - Transformer tf = TransformerFactory.newInstance().newTransformer(); - tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$ - tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ - tf.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ - tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", //$NON-NLS-1$ - "4"); //$NON-NLS-1$ - tf.transform(new DOMSource(doc), new StreamResult(outFile)); - return true; - } catch (TransformerException e) { - log.error(Severity.ERROR, - new FileAndLine(outFile.getName(), 0), - "Failed to write XML file: %1$s", - e.toString()); - return false; - } - } - - /** - * Outputs the given XML {@link Document} as a string. - * - * TODO right now reformats the document. Needs to output as-is, respecting white-space. - * - * @param doc The document to output. Must not be null. - * @param log A log in case of error. - * @return A string representation of the XML. Null in case of error. - */ - static String printXmlString( - @NonNull Document doc, - @NonNull IMergerLog log) { - try { - Transformer tf = TransformerFactory.newInstance().newTransformer(); - tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$ - tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$ - tf.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ - tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", //$NON-NLS-1$ - "4"); //$NON-NLS-1$ - StringWriter sw = new StringWriter(); - tf.transform(new DOMSource(doc), new StreamResult(sw)); - return sw.toString(); - } catch (TransformerException e) { - log.error(Severity.ERROR, - new FileAndLine(extractXmlFilename(doc), 0), - "Failed to write XML file: %1$s", - e.toString()); - return null; - } - } - - /** - * Dumps the structure of the DOM to a simple text string. - * - * @param node The first node to dump (recursively). Can be null. - * @param nextSiblings If true, will also dump the following siblings. - * If false, it will just process the given node. - * @return A string representation of the Node structure, useful for debugging. - */ - @NonNull - static String dump(@Nullable Node node, boolean nextSiblings) { - return dump(node, 0 /*offset*/, nextSiblings, true /*deep*/, null /*keyAttr*/); - } - - - /** - * Dumps the structure of the DOM to a simple text string. - * Each line is terminated with a \n separator. - * - * @param node The first node to dump. Can be null. - * @param offsetIndex The offset to add at the begining of each line. Each offset is - * converted into 2 space characters. - * @param nextSiblings If true, will also dump the following siblings. - * If false, it will just process the given node. - * @param deep If true, this will recurse into children. - * @param keyAttr An optional attribute *local* name to insert when writing an element. - * For example when writing an Activity, it helps to always insert "name" attribute. - * @return A string representation of the Node structure, useful for debugging. - */ - @NonNull - static String dump( - @Nullable Node node, - int offsetIndex, - boolean nextSiblings, - boolean deep, - @Nullable String keyAttr) { - StringBuilder sb = new StringBuilder(); - - String offset = ""; //$NON-NLS-1$ - for (int i = 0; i < offsetIndex; i++) { - offset += " "; //$NON-NLS-1$ - } - - if (node == null) { - sb.append(offset).append("(end reached)\n"); - - } else { - for (; node != null; node = node.getNextSibling()) { - String type = null; - short t = node.getNodeType(); - switch(t) { - case Node.ELEMENT_NODE: - String attr = ""; - if (keyAttr != null) { - NamedNodeMap attrs = node.getAttributes(); - if (attrs != null) { - for (int i = 0; i < attrs.getLength(); i++) { - Node a = attrs.item(i); - if (a != null && keyAttr.equals(a.getLocalName())) { - attr = String.format(" %1$s=%2$s", - a.getNodeName(), a.getNodeValue()); - break; - } - } - } - } - sb.append(String.format("%1$s<%2$s%3$s>\n", - offset, node.getNodeName(), attr)); - break; - case Node.COMMENT_NODE: - sb.append(String.format("%1$s<!-- %2$s -->\n", - offset, node.getNodeValue())); - break; - case Node.TEXT_NODE: - String txt = node.getNodeValue().trim(); - if (txt.length() == 0) { - // Keep this for debugging. TODO make it a flag - // to dump whitespace on debugging. Otherwise ignore it. - // txt = "[whitespace]"; - break; - } - sb.append(String.format("%1$s%2$s\n", offset, txt)); - break; - case Node.ATTRIBUTE_NODE: - sb.append(String.format("%1$s @%2$s = %3$s\n", - offset, node.getNodeName(), node.getNodeValue())); - break; - case Node.CDATA_SECTION_NODE: - type = "cdata"; //$NON-NLS-1$ - break; - case Node.DOCUMENT_NODE: - type = "document"; //$NON-NLS-1$ - break; - case Node.PROCESSING_INSTRUCTION_NODE: - type = "PI"; //$NON-NLS-1$ - break; - default: - type = Integer.toString(t); - } - - if (type != null) { - sb.append(String.format("%1$s[%2$s] <%3$s> %4$s\n", - offset, type, node.getNodeName(), node.getNodeValue())); - } - - if (deep) { - List<Attr> attrs = sortedAttributeList(node.getAttributes()); - for (Attr attr : attrs) { - sb.append(String.format("%1$s @%2$s = %3$s\n", - offset, attr.getNodeName(), attr.getNodeValue())); - } - - Node child = node.getFirstChild(); - if (child != null) { - sb.append(dump(child, offsetIndex+1, true, true, keyAttr)); - } - } - - if (!nextSiblings) { - break; - } - } - } - return sb.toString(); - } - - /** - * Returns a sorted list of attributes. - * The list is never null and does not contain null items. - * - * @param attrMap A Node map as returned by {@link Node#getAttributes()}. - * Can be null, in which case an empty list is returned. - * @return A non-null, possible empty, list of all nodes that are actual {@link Attr}, - * sorted by increasing attribute name. - */ - @NonNull - static List<Attr> sortedAttributeList(@Nullable NamedNodeMap attrMap) { - List<Attr> list = new ArrayList<Attr>(); - - if (attrMap != null) { - for (int i = 0; i < attrMap.getLength(); i++) { - Node attr = attrMap.item(i); - if (attr instanceof Attr) { - list.add((Attr) attr); - } - } - } - - if (list.size() > 1) { - // Sort it by attribute name - Collections.sort(list, getAttrComparator()); - } - - return list; - } - - /** - * Returns a comparator for {@link Attr}, alphabetically sorted by name. - * The "name" attribute is special and always sorted to the front. - */ - @NonNull - static Comparator<? super Attr> getAttrComparator() { - return new Comparator<Attr>() { - @Override - public int compare(Attr a1, Attr a2) { - String s1 = a1 == null ? "" : a1.getNodeName(); //$NON-NLS-1$ - String s2 = a2 == null ? "" : a2.getNodeValue(); //$NON-NLS-1$ - - int prio1 = s1.equals("name") ? 0 : 1; //$NON-NLS-1$ - int prio2 = s2.equals("name") ? 0 : 1; //$NON-NLS-1$ - if (prio1 == 0 || prio2 == 0) { - return prio1 - prio2; - } - - return s1.compareTo(s2); - } - }; - } - - /** - * Inject attributes into an existing document. - * <p/> - * The map keys are "/manifest/elements...|attribute-ns-uri attribute-local-name", - * for example "/manifest/uses-sdk|http://schemas.android.com/apk/res/android minSdkVersion". - * (note the space separator between the attribute URI and its local name.) - * The elements will be created if they don't exists. Existing attributes will be modified. - * The replacement is done on the main document <em>before</em> merging. - * The value can be null to remove an existing attribute. - * - * @param doc The document to modify in-place. - * @param attributeMap A map of attributes to inject in the form [pseudo-xpath] => value. - * @param log A log in case of error. - */ - static void injectAttributes( - @Nullable Document doc, - @Nullable Map<String, String> attributeMap, - @NonNull IMergerLog log) { - if (doc == null || attributeMap == null || attributeMap.isEmpty()) { - return; - } - - // 1=path 2=URI 3=local name - final Pattern keyRx = Pattern.compile("^/([^\\|]+)\\|([^ ]*) +(.+)$"); //$NON-NLS-1$ - final FileAndLine docInfo = xmlFileAndLine(doc); - - nextAttribute: for (Entry<String, String> entry : attributeMap.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (key == null || key.isEmpty()) { - continue; - } - - Matcher m = keyRx.matcher(key); - if (!m.matches()) { - log.error(Severity.WARNING, docInfo, "Invalid injected attribute key: %s", key); - continue; - } - String path = m.group(1); - String attrNsUri = m.group(2); - String attrName = m.group(3); - - String[] segment = path.split(Pattern.quote("/")); //$NON-NLS-1$ - - // Get the path elements. Create them as needed if they don't exist. - Node element = doc; - nextSegment: for (int i = 0; i < segment.length; i++) { - // Find a child with the segment's name - String name = segment[i]; - for (Node child = element.getFirstChild(); - child != null; - child = child.getNextSibling()) { - if (child.getNodeType() == Node.ELEMENT_NODE && - child.getNamespaceURI() == null && - child.getNodeName().equals(name)) { - // Found it. Continue to the next inner segment. - element = child; - continue nextSegment; - } - } - // No such element. Create it. - if (value == null) { - // If value is null, we want to remove, not create and if can't find the - // element, then we're done: there's no such attribute to remove. - break nextAttribute; - } - - Element child = doc.createElement(name); - element = element.insertBefore(child, element.getFirstChild()); - } - - if (element == null) { - log.error(Severity.WARNING, docInfo, "Invalid injected attribute path: %s", path); - return; - } - - NamedNodeMap attrs = element.getAttributes(); - if (attrs != null) { - - - if (attrNsUri != null && attrNsUri.isEmpty()) { - attrNsUri = null; - } - Node attr = attrs.getNamedItemNS(attrNsUri, attrName); - - if (value == null) { - // We want to remove the attribute from the attribute map. - if (attr != null) { - attrs.removeNamedItemNS(attrNsUri, attrName); - } - - } else { - // We want to add or replace the attribute. - if (attr == null) { - attr = doc.createAttributeNS(attrNsUri, attrName); - if (attrNsUri != null) { - attr.setPrefix(XmlUtils.lookupNamespacePrefix(element, attrNsUri)); - } - attrs.setNamedItemNS(attr); - } - attr.setNodeValue(value); - } - } - } - } - - // ------- - - /** - * Flatten the element to a string. This "pretty prints" the XML tree starting - * from the given node and all its children and attributes. - * <p/> - * The output is designed to be printed using {@link #printXmlDiff}. - * - * @param node The root node to print. - * @param nsPrefix A map that is filled with all the URI=>prefix found. - * The internal string only contains the expanded URIs but this is rather verbose - * so when printing the diff these will be replaced by the prefixes collected here. - * @param prefix A "space" prefix added at the beginning of each line for indentation - * purposes. The diff printer later relies on this to find out the structure. - */ - @NonNull - static String printElement( - @NonNull Node node, - @NonNull Map<String, String> nsPrefix, - @NonNull String prefix) { - StringBuilder sb = new StringBuilder(); - sb.append(prefix).append('<'); - String uri = node.getNamespaceURI(); - if (uri != null) { - sb.append(uri).append(':'); - nsPrefix.put(uri, node.getPrefix()); - } - sb.append(node.getLocalName()); - printAttributes(sb, node, nsPrefix, prefix); - sb.append(">\n"); //$NON-NLS-1$ - printChildren(sb, node.getFirstChild(), true, nsPrefix, prefix + " "); //$NON-NLS-1$ - - sb.append(prefix).append("</"); //$NON-NLS-1$ - if (uri != null) { - sb.append(uri).append(':'); - } - sb.append(node.getLocalName()); - sb.append(">\n"); //$NON-NLS-1$ - - return sb.toString(); - } - - /** - * Flatten several children elements to a string. - * This is an implementation detail for {@link #printElement(Node, Map, String)}. - * <p/> - * If {@code nextSiblings} is false, the string conversion takes only the given - * child element and stops there. - * <p/> - * If {@code nextSiblings} is true, the string conversion also takes _all_ the siblings - * after the given element. The idea is the caller can call this with the first child - * of a parent and get a string showing all the children at the same time. They are - * sorted to avoid the ordering issue. - */ - @NonNull - private static StringBuilder printChildren( - @NonNull StringBuilder sb, - @NonNull Node child, - boolean nextSiblings, - @NonNull Map<String, String> nsPrefix, - @NonNull String prefix) { - ArrayList<String> children = new ArrayList<String>(); - - boolean hasText = false; - for (; child != null; child = child.getNextSibling()) { - short t = child.getNodeType(); - if (nextSiblings && t == Node.TEXT_NODE) { - // We don't typically have meaningful text nodes in an Android manifest. - // If there are, just dump them as-is into the element representation. - // We do trim whitespace and ignore all-whitespace or empty text nodes. - String s = child.getNodeValue().trim(); - if (s.length() > 0) { - sb.append(s); - hasText = true; - } - } else if (t == Node.ELEMENT_NODE) { - children.add(printElement(child, nsPrefix, prefix)); - if (!nextSiblings) { - break; - } - } - } - - if (hasText) { - sb.append('\n'); - } - - if (!children.isEmpty()) { - Collections.sort(children); - for (String s : children) { - sb.append(s); - } - } - - return sb; - } - - /** - * Flatten several attributes to a string using their alphabethical order. - * This is an implementation detail for {@link #printElement(Node, Map, String)}. - */ - @NonNull - private static StringBuilder printAttributes( - @NonNull StringBuilder sb, - @NonNull Node node, - @NonNull Map<String, String> nsPrefix, - @NonNull String prefix) { - ArrayList<String> attrs = new ArrayList<String>(); - - NamedNodeMap attrMap = node.getAttributes(); - if (attrMap != null) { - StringBuilder sb2 = new StringBuilder(); - for (int i = 0; i < attrMap.getLength(); i++) { - Node attr = attrMap.item(i); - if (attr instanceof Attr) { - sb2.setLength(0); - sb2.append('@'); - String uri = attr.getNamespaceURI(); - if (uri != null) { - sb2.append(uri).append(':'); - nsPrefix.put(uri, attr.getPrefix()); - } - sb2.append(attr.getLocalName()); - sb2.append("=\"").append(attr.getNodeValue()).append('\"'); //$NON-NLS-1$ - attrs.add(sb2.toString()); - } - } - } - - Collections.sort(attrs); - - for(String attr : attrs) { - sb.append('\n'); - sb.append(prefix).append(" ").append(attr); //$NON-NLS-1$ - } - return sb; - } - - //------------ - - /** - * Computes a quick diff between two strings generated by - * {@link #printElement(Node, Map, String)}. - * <p/> - * This is a <em>not</em> designed to be a full contextual diff. - * It just stops at the first difference found, printing up to 3 lines of diff - * and backtracking to add prior contextual information to understand the - * structure of the element where the first diff line occured (by printing - * each parent found till the root one as well as printing the attribute - * named by {@code keyAttr}). - * - * @param sb The string builder where to output is written. - * @param expected The expected XML tree (as generated by {@link #printElement}.) - * For best result this would be the "destination" XML we're merging into, - * e.g. the main manifest. - * @param actual The actual XML tree (as generated by {@link #printElement}.) - * For best result this would be the "source" XML we're merging from, - * e.g. a library manifest. - * @param nsPrefixE The map of URI=>prefix for the expected XML tree. - * @param nsPrefixA The map of URI=>prefix for the actual XML tree. - * @param keyAttr An optional attribute *full* name (uri:local name) to always - * insert when writing the contextual lines before a diff line. - * For example when writing an Activity, it helps to always insert - * the "name" attribute since that's the key element to help the user - * identify which node is being dumped. - */ - static void printXmlDiff( - StringBuilder sb, - String expected, - String actual, - Map<String, String> nsPrefixE, - Map<String, String> nsPrefixA, - String keyAttr) { - String[] aE = expected.split("\n"); - String[] aA = actual.split("\n"); - int lE = aE.length; - int lA = aA.length; - int lm = lE < lA ? lA : lE; - boolean eofE = false; - boolean eofA = false; - boolean contextE = true; - boolean contextA = true; - int numDiff = 0; - - StringBuilder sE = new StringBuilder(); - StringBuilder sA = new StringBuilder(); - - outerLoop: for (int i = 0, iE = 0, iA = 0; i < lm; i++) { - if (iE < lE && iA < lA && aE[iE].equals(aA[iA])) { - if (numDiff > 0) { - // If we found a difference, stop now. - break outerLoop; - } - iE++; - iA++; - continue; - } else { - // Try to print some context for each side based on previous lines's space prefix. - if (contextE) { - if (iE > 0) { - String p = diffGetPrefix(aE[iE]); - for (int kE = iE-1; kE >= 0; kE--) { - if (!aE[kE].startsWith(p)) { - sE.insert(0, '\n').insert(0, diffReplaceNs(aE[kE], nsPrefixE)).insert(0, " "); - if (p.length() == 0) { - break; - } - p = diffGetPrefix(aE[kE]); - } else if (aE[kE].contains(keyAttr) || kE == 0) { - sE.insert(0, '\n').insert(0, diffReplaceNs(aE[kE], nsPrefixE)).insert(0, " "); - } - } - } - contextE = false; - } - if (iE >= lE) { - if (!eofE) { - sE.append("--(end reached)\n"); - eofE = true; - } - } else { - sE.append("--").append(diffReplaceNs(aE[iE++], nsPrefixE)).append('\n'); - } - - if (contextA) { - if (iA > 0) { - String p = diffGetPrefix(aA[iA]); - for (int kA = iA-1; kA >= 0; kA--) { - if (!aA[kA].startsWith(p)) { - sA.insert(0, '\n').insert(0, diffReplaceNs(aA[kA], nsPrefixA)).insert(0, " "); - p = diffGetPrefix(aA[kA]); - if (p.length() == 0) { - break; - } - } else if (aA[kA].contains(keyAttr) || kA == 0) { - sA.insert(0, '\n').insert(0, diffReplaceNs(aA[kA], nsPrefixA)).insert(0, " "); - } - } - } - contextA = false; - } - if (iA >= lA) { - if (!eofA) { - sA.append("++(end reached)\n"); - eofA = true; - } - } else { - sA.append("++").append(diffReplaceNs(aA[iA++], nsPrefixA)).append('\n'); - } - - // Dump up to 3 lines of difference - numDiff++; - if (numDiff == 3) { - break outerLoop; - } - } - } - - sb.append(sE); - sb.append(sA); - } - - /** - * Returns all the whitespace at the beginning of a string. - * Implementation details for {@link #printXmlDiff} used to find the "parent" - * element and include it in the context of the diff. - */ - private static String diffGetPrefix(String str) { - int pos = 0; - int len = str.length(); - while (pos < len && str.charAt(pos) == ' ') { - pos++; - } - return str.substring(0, pos); - } - - /** - * Simplifies a diff line by replacing NS URIs by their prefix. - * Implementation details for {@link #printXmlDiff}. - */ - private static String diffReplaceNs(String str, Map<String, String> nsPrefix) { - for (Entry<String, String> entry : nsPrefix.entrySet()) { - String uri = entry.getKey(); - String prefix = entry.getValue(); - if (prefix != null && str.contains(uri)) { - str = str.replaceAll(Pattern.quote(uri), Matcher.quoteReplacement(prefix)); - } - } - return str; - } - -} diff --git a/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTest.java b/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTest.java deleted file mode 100755 index a5d0aa1..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - - -/** - * Unit tests for {@link ManifestMerger}. - */ -public class ManifestMergerTest extends ManifestMergerTestCase { - - /* - * Wait, I hear you, where are the tests? - * - * processTestFiles() uses loadTestData(), which infers the data filename - * from the caller method name. - * E.g. the method "test00_noop" will use the data file named "data/00_noop.xml". - * - * We could simplify this even further by simply iterating on the data - * files and getting rid of the test methods; however there's some value in - * having tests break on a method name that easily points to the data file. - */ - - public void test00_noop() throws Exception { - processTestFiles(); - } - - public void test01_ignore_app_attr() throws Exception { - processTestFiles(); - } - - public void test02_ignore_instrumentation() throws Exception { - processTestFiles(); - } - - public void test03_inject_attributes() throws Exception { - processTestFiles(); - } - - public void test04_inject_attributes() throws Exception { - processTestFiles(); - } - - public void test10_activity_merge() throws Exception { - processTestFiles(); - } - - public void test11_activity_dup() throws Exception { - processTestFiles(); - } - - public void test12_alias_dup() throws Exception { - processTestFiles(); - } - - public void test13_service_dup() throws Exception { - processTestFiles(); - } - - public void test14_receiver_dup() throws Exception { - processTestFiles(); - } - - public void test15_provider_dup() throws Exception { - processTestFiles(); - } - - public void test16_fqcn_merge() throws Exception { - processTestFiles(); - } - - public void test17_fqcn_conflict() throws Exception { - processTestFiles(); - } - - public void test20_uses_lib_merge() throws Exception { - processTestFiles(); - } - - public void test21_uses_lib_errors() throws Exception { - processTestFiles(); - } - - public void test25_permission_merge() throws Exception { - processTestFiles(); - } - - public void test26_permission_dup() throws Exception { - processTestFiles(); - } - - public void test28_uses_perm_merge() throws Exception { - processTestFiles(); - } - - public void test30_uses_sdk_ok() throws Exception { - processTestFiles(); - } - - public void test32_uses_sdk_minsdk_ok() throws Exception { - processTestFiles(); - } - - public void test33_uses_sdk_minsdk_conflict() throws Exception { - processTestFiles(); - } - - public void test36_uses_sdk_targetsdk_warning() throws Exception { - processTestFiles(); - } - - public void test40_uses_feat_merge() throws Exception { - processTestFiles(); - } - - public void test41_uses_feat_errors() throws Exception { - processTestFiles(); - } - - public void test45_uses_feat_gles_once() throws Exception { - processTestFiles(); - } - - public void test47_uses_feat_gles_conflict() throws Exception { - processTestFiles(); - } - - public void test50_uses_conf_warning() throws Exception { - processTestFiles(); - } - - public void test52_support_screens_warning() throws Exception { - processTestFiles(); - } - - public void test54_compat_screens_warning() throws Exception { - processTestFiles(); - } - - public void test56_support_gltext_warning() throws Exception { - processTestFiles(); - } - - public void test60_merge_order() throws Exception { - processTestFiles(); - } - - public void test65_override_app() throws Exception { - processTestFiles(); - } - - public void test66_remove_app() throws Exception { - processTestFiles(); - } - - public void test67_override_activities() throws Exception { - processTestFiles(); - } - - public void test68_override_uses() throws Exception { - processTestFiles(); - } - - public void test69_remove_uses() throws Exception { - processTestFiles(); - } - - public void test70_expand_fqcns() throws Exception { - processTestFiles(); - } - - public void test71_extract_package_prefix() throws Exception { - processTestFiles(); - } - - public void test75_app_metadata_merge() throws Exception { - processTestFiles(); - } - - public void test76_app_metadata_ignore() throws Exception { - processTestFiles(); - } - - public void test77_app_metadata_conflict() throws Exception { - processTestFiles(); - } -} diff --git a/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTestCase.java b/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTestCase.java deleted file mode 100755 index 29378f0..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/ManifestMergerTestCase.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.manifmerger; - -import com.android.annotations.NonNull; -import com.android.manifmerger.IMergerLog.FileAndLine; -import com.android.sdklib.mock.MockLog; - -import org.w3c.dom.Document; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import junit.framework.TestCase; - -/** - * Some utilities to reduce repetitions in the {@link ManifestMergerTest}s. - * <p/> - * See {@link #loadTestData(String)} for an explanation of the data file format. - */ -abstract class ManifestMergerTestCase extends TestCase { - - /** - * Delimiter that indicates the test must fail. - * An XML output and errors are still generated and checked. - */ - private static final String DELIM_FAILS = "fails"; - /** - * Delimiter that starts a library XML content. - * The delimiter name must be in the form {@code @libSomeName} and it will be - * used as the base for the test file name. Using separate lib names is encouraged - * since it makes the error output easier to read. - */ - private static final String DELIM_LIB = "lib"; - /** - * Delimiter that starts the main manifest XML content. - */ - private static final String DELIM_MAIN = "main"; - /** - * Delimiter that starts the resulting XML content, whatever is generated by the merge. - */ - private static final String DELIM_RESULT = "result"; - /** - * Delimiter that starts the SdkLog output. - * The logger prints each entry on its lines, prefixed with E for errors, - * W for warnings and P for regular printfs. - */ - private static final String DELIM_ERRORS = "errors"; - /** - * Delimiter for starts a section that declares how to inject an attribute. - * The section is composed of one or more lines with the - * syntax: "/node/node|attr-URI attrName=attrValue". - * This is essentially a pseudo XPath-like expression that is described in - * {@link ManifestMerger#process(Document, File[], Map)}. - */ - private static final String DELIM_INJECT_ATTR = "inject"; - /** - * Delimiter for a section that declares how to toggle a ManifMerger option. - * The section is composed of one or more lines with the - * syntax: "functionName=false|true". - */ - private static final String DELIM_FEATURES = "features"; - - static class TestFiles { - private final File mMain; - private final File[] mLibs; - private final Map<String, String> mInjectAttributes; - private final File mActualResult; - private final String mExpectedResult; - private final String mExpectedErrors; - private final boolean mShouldFail; - private final Map<String, Boolean> mFeatures; - - /** Files used by a given test case. */ - public TestFiles( - boolean shouldFail, - @NonNull File main, - @NonNull File[] libs, - @NonNull Map<String, Boolean> features, - @NonNull Map<String, String> injectAttributes, - @NonNull File actualResult, - @NonNull String expectedResult, - @NonNull String expectedErrors) { - mShouldFail = shouldFail; - mMain = main; - mLibs = libs; - mFeatures = features; - mInjectAttributes = injectAttributes; - mActualResult = actualResult; - mExpectedResult = expectedResult; - mExpectedErrors = expectedErrors; - } - - public boolean getShouldFail() { - return mShouldFail; - } - - @NonNull - public File getMain() { - return mMain; - } - - @NonNull - public File[] getLibs() { - return mLibs; - } - - public Map<String, Boolean> getFeatures() { - return mFeatures; - } - - public Map<String, String> getInjectAttributes() { - return mInjectAttributes; - } - - @NonNull - public File getActualResult() { - return mActualResult; - } - - @NonNull - public String getExpectedResult() { - return mExpectedResult; - } - - public String getExpectedErrors() { - return mExpectedErrors; - } - - // Try to delete any temp file potentially created. - public void cleanup() { - if (mMain != null && mMain.isFile()) { - mMain.delete(); - } - - if (mActualResult != null && mActualResult.isFile()) { - mActualResult.delete(); - } - - for (File f : mLibs) { - if (f != null && f.isFile()) { - f.delete(); - } - } - } - } - - /** - * Calls {@link #loadTestData(String)} by - * inferring the data filename from the caller's method name. - * <p/> - * The caller method name must be composed of "test" + the leaf filename. - * Extensions ".xml" or ".txt" are implied. - * <p/> - * E.g. to use the data file "12_foo.xml", simply call this from a method - * named "test12_foo". - * - * @return A new {@link TestFiles} instance. Never null. - * @throws Exception when things go wrong. - * @see #loadTestData(String) - */ - @NonNull - TestFiles loadTestData() throws Exception { - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - for (int i = 0, n = stack.length; i < n; i++) { - StackTraceElement caller = stack[i]; - String name = caller.getMethodName(); - if (name.startsWith("test")) { - return loadTestData(name.substring(4)); - } - } - - throw new IllegalArgumentException("No caller method found which name started with 'test'"); - } - - /** - * Loads test data for a given test case. - * The input (main + libs) are stored in temp files. - * A new destination temp file is created to store the actual result output. - * The expected result is actually kept in a string. - * <p/> - * Data File Syntax: - * <ul> - * <li> Lines starting with # are ignored (anywhere, as long as # is the first char). - * <li> Lines before the first {@code @delimiter} are ignored. - * <li> Empty lines just after the {@code @delimiter} - * and before the first < XML line are ignored. - * <li> Valid delimiters are {@code @main} for the XML of the main app manifest. - * <li> Following delimiters are {@code @libXYZ}, read in the order of definition. - * The name can be anything as long as it starts with "{@code @lib}". - * </ul> - * - * @param filename The test data filename. If no extension is provided, this will - * try with .xml or .txt. Must not be null. - * @return A new {@link TestFiles} instance. Must not be null. - * @throws Exception when things fail to load properly. - */ - @NonNull - TestFiles loadTestData(@NonNull String filename) throws Exception { - - String resName = "data" + File.separator + filename; - InputStream is = null; - BufferedReader reader = null; - BufferedWriter writer = null; - - try { - is = this.getClass().getResourceAsStream(resName); - if (is == null && !filename.endsWith(".xml")) { - String resName2 = resName + ".xml"; - is = this.getClass().getResourceAsStream(resName2); - if (is != null) { - filename = resName2; - } - } - if (is == null && !filename.endsWith(".txt")) { - String resName3 = resName + ".txt"; - is = this.getClass().getResourceAsStream(resName3); - if (is != null) { - filename = resName3; - } - } - assertNotNull("Test data file not found for " + filename, is); - - reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - - // Get the temporary directory to use. Just create a temp file, extracts its - // directory and remove the file. - File tempFile = File.createTempFile(this.getClass().getSimpleName(), ".tmp"); - File tempDir = tempFile.getParentFile(); - if (!tempFile.delete()) { - tempFile.deleteOnExit(); - } - - String line = null; - String delimiter = null; - boolean skipEmpty = true; - - boolean shouldFail = false; - Map<String, Boolean> features = new HashMap<String, Boolean>(); - Map<String, String> injectAttributes = new HashMap<String, String>(); - StringBuilder expectedResult = new StringBuilder(); - StringBuilder expectedErrors = new StringBuilder(); - File mainFile = null; - File actualResultFile = null; - List<File> libFiles = new ArrayList<File>(); - int tempIndex = 0; - - while ((line = reader.readLine()) != null) { - if (skipEmpty && line.trim().length() == 0) { - continue; - } - if (line.length() > 0 && line.charAt(0) == '#') { - continue; - } - if (line.length() > 0 && line.charAt(0) == '@') { - delimiter = line.substring(1); - assertTrue( - "Unknown delimiter @" + delimiter + " in " + filename, - delimiter.startsWith(DELIM_LIB) || - delimiter.equals(DELIM_MAIN) || - delimiter.equals(DELIM_RESULT) || - delimiter.equals(DELIM_ERRORS) || - delimiter.equals(DELIM_FAILS) || - delimiter.equals(DELIM_FEATURES) || - delimiter.equals(DELIM_INJECT_ATTR)); - - skipEmpty = true; - - if (writer != null) { - try { - writer.close(); - } catch (IOException ignore) {} - writer = null; - } - - if (delimiter.equals(DELIM_FAILS)) { - shouldFail = true; - - } else if (!delimiter.equals(DELIM_ERRORS) && - !delimiter.equals(DELIM_FEATURES) && - !delimiter.equals(DELIM_INJECT_ATTR)) { - tempFile = new File(tempDir, String.format("%1$s%2$d_%3$s.xml", - this.getClass().getSimpleName(), - tempIndex++, - delimiter.replaceAll("[^a-zA-Z0-9_-]", "") - )); - tempFile.deleteOnExit(); - - if (delimiter.startsWith(DELIM_LIB)) { - libFiles.add(tempFile); - - } else if (delimiter.equals(DELIM_MAIN)) { - mainFile = tempFile; - - } else if (delimiter.equals(DELIM_RESULT)) { - actualResultFile = tempFile; - - } else { - fail("Unexpected data file delimiter @" + delimiter + - " in " + filename); - } - - if (!delimiter.equals(DELIM_RESULT)) { - writer = new BufferedWriter(new FileWriter(tempFile)); - } - } - - continue; - } - if (delimiter != null && - skipEmpty && - line.length() > 0 && - line.charAt(0) != '#' && - line.charAt(0) != '@') { - skipEmpty = false; - } - if (writer != null) { - writer.write(line); - writer.write('\n'); - } else if (DELIM_RESULT.equals(delimiter)) { - expectedResult.append(line).append('\n'); - } else if (DELIM_ERRORS.equals(delimiter)) { - expectedErrors.append(line).append('\n'); - } else if (DELIM_INJECT_ATTR.equals(delimiter)) { - String[] in = line.split("="); - if (in != null && in.length == 2) { - injectAttributes.put(in[0], "null".equals(in[1]) ? null : in[1]); - } - } else if (DELIM_FEATURES.equals(delimiter)) { - String[] in = line.split("="); - if (in != null && in.length == 2) { - features.put(in[0], Boolean.parseBoolean(in[1])); - } - } - } - - assertNotNull("Missing @" + DELIM_MAIN + " in " + filename, mainFile); - assertNotNull("Missing @" + DELIM_RESULT + " in " + filename, actualResultFile); - - assert mainFile != null; - assert actualResultFile != null; - - return new TestFiles( - shouldFail, - mainFile, - libFiles.toArray(new File[libFiles.size()]), - features, - injectAttributes, - actualResultFile, - expectedResult.toString(), - expectedErrors.toString()); - - } catch (UnsupportedEncodingException e) { - // BufferedReader failed to decode UTF-8, O'RLY? - throw e; - - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException ignore) {} - } - if (reader != null) { - try { - reader.close(); - } catch (IOException ignore) {} - } - if (is != null) { - try { - is.close(); - } catch (IOException ignore) {} - } - } - } - - /** - * Loads the data test files using {@link #loadTestData()} and then - * invokes {@link #processTestFiles(TestFiles)} to test them. - * - * @see #loadTestData() - * @see #processTestFiles(TestFiles) - */ - void processTestFiles() throws Exception { - processTestFiles(loadTestData()); - } - - /** - * Processes the data from the given {@link TestFiles} by - * invoking {@link ManifestMerger#process(File, File, File[], Map)}: - * the given library files are applied consecutively to the main XML - * document and the output is generated. - * <p/> - * Then the expected and actual outputs are loaded into a DOM, - * dumped again to a String using an XML transform and compared. - * This makes sure only the structure is checked and that any - * formatting is ignored in the comparison. - * - * @param testFiles The test files to process. Must not be null. - * @throws Exception when this go wrong. - */ - void processTestFiles(TestFiles testFiles) throws Exception { - MockLog log = new MockLog(); - IMergerLog mergerLog = MergerLog.wrapSdkLog(log); - ManifestMerger merger = new ManifestMerger(mergerLog, new ICallback() { - @Override - public int queryCodenameApiLevel(@NonNull String codename) { - if ("ApiCodename1".equals(codename)) { - return 1; - } else if ("ApiCodename10".equals(codename)) { - return 10; - } - return ICallback.UNKNOWN_CODENAME; - } - }); - - for (Entry<String, Boolean> feature : testFiles.getFeatures().entrySet()) { - Method m = merger.getClass().getMethod( - feature.getKey(), - new Class<?>[] { boolean.class } ); - m.invoke(merger, new Object[] { feature.getValue() } ); - } - - boolean processOK = merger.process(testFiles.getActualResult(), - testFiles.getMain(), - testFiles.getLibs(), - testFiles.getInjectAttributes()); - - String expectedErrors = testFiles.getExpectedErrors().trim(); - StringBuilder actualErrors = new StringBuilder(); - for (String s : log.getMessages()) { - actualErrors.append(s); - if (!s.endsWith("\n")) { - actualErrors.append('\n'); - } - } - assertEquals("Error generated during merging", - expectedErrors, actualErrors.toString().trim()); - - if (testFiles.getShouldFail()) { - assertFalse("Merge process() returned true, expected false", processOK); - } else { - assertTrue("Merge process() returned false, expected true", processOK); - } - - // Test result XML. There should always be one created - // since the process action does not stop on errors. - log.clear(); - Document document = MergerXmlUtils.parseDocument(testFiles.getActualResult(), mergerLog); - assertNotNull(document); - assert document != null; // for Eclipse null analysis - String actual = MergerXmlUtils.printXmlString(document, mergerLog); - assertEquals("Error parsing actual result XML", "[]", log.toString()); - log.clear(); - document = MergerXmlUtils.parseDocument( - testFiles.getExpectedResult(), - mergerLog, - new FileAndLine("<expected-result>", 0)); - assertNotNull("Failed to parse result document: " + testFiles.getExpectedResult(),document); - assert document != null; - String expected = MergerXmlUtils.printXmlString(document, mergerLog); - assertEquals("Error parsing expected result XML", "[]", log.toString()); - assertEquals("Error comparing expected to actual result", expected, actual); - - testFiles.cleanup(); - } - -} diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/00_noop.xml b/manifmerger/src/test/java/com/android/manifmerger/data/00_noop.xml deleted file mode 100755 index 2160f69..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/00_noop.xml +++ /dev/null @@ -1,229 +0,0 @@ -# -# Syntax: -# - Lines starting with # are ignored (anywhere, as long as # is the first char). -# - Lines before the first @delimiter are ignored. -# - Empty lines just after the @delimiter and before the first < XML line are ignored. -# - Valid delimiters are @main for the XML of the main app manifest. -# - Following delimiters are @libXYZ, read in the order of definition. The name can be -# anything as long as it starts with "@lib". -# - Last delimiter should be @result. -# - -@main - -<!-- - This is a canonical manifest that has some uses-permissions, - the usual uses-sdk and supports-screens, an app with an activity, - customer receiver & service and a widget. ---> - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Activity to configure widget --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <intent-filter > - <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider android:name=".app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> -</manifest> - - -@lib2 - -# An empty library is not supported. It must be a valid XML file. -<manifest/> - -@result - -<!-- - This is a canonical manifest that has some uses-permissions, - the usual uses-sdk and supports-screens, an app with an activity, - customer receiver & service and a widget. ---> - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Activity to configure widget --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <intent-filter > - <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider - android:name="com.example.app1.app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - - </application> - -</manifest> - - -@errors - -W [ManifestMergerTest2_lib2.xml:1] Missing 'package' attribute in manifest. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/01_ignore_app_attr.xml b/manifmerger/src/test/java/com/android/manifmerger/data/01_ignore_app_attr.xml deleted file mode 100755 index b939dd7..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/01_ignore_app_attr.xml +++ /dev/null @@ -1,69 +0,0 @@ -# -# Test: -# - Attributes from the application element in a library are ignored (except name) -# - Comments from nodes ignored in libraries are not merged either. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- Source comments are preserved as-is. --> - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- The attributes from <application> in a library are not merged nor checked - except for 'name' and 'backupAgent' which must match. - This comment is ignored. --> - <application - android:label="@string/lib_name" - android:icon="@drawable/lib_icon" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- Source comments are preserved as-is. --> - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/02_ignore_instrumentation.xml b/manifmerger/src/test/java/com/android/manifmerger/data/02_ignore_instrumentation.xml deleted file mode 100755 index ed0dbbc..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/02_ignore_instrumentation.xml +++ /dev/null @@ -1,62 +0,0 @@ -# -# Test: -# - Instrumentation element from libraries are not merged in main manifest. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- Instrumentation is not merged from libraries. --> - <instrumentation - android:targetPackage="com.example.app1" - android:name="android.test.InstrumentationTestRunner" /> - -</manifest> - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/03_inject_attributes.xml b/manifmerger/src/test/java/com/android/manifmerger/data/03_inject_attributes.xml deleted file mode 100755 index 0a7057c..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/03_inject_attributes.xml +++ /dev/null @@ -1,53 +0,0 @@ -# -# Test: -# - Inject attributes in a main manifest. -# - -@inject -/manifest|http://schemas.android.com/apk/res/android versionCode=101 -/manifest|http://schemas.android.com/apk/res/android versionName=1.0.1 -/manifest/uses-sdk|http://schemas.android.com/apk/res/android minSdkVersion=10 -/manifest/uses-sdk|http://schemas.android.com/apk/res/android targetSdkVersion=14 -/manifest/application|http://schemas.android.com/apk/res/android label=null -/manifest/application|http://schemas.android.com/apk/res/android icon=null - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="101" - android:versionName="1.0.1"><uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14"/> - - <application - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - </application> - -</manifest> - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/04_inject_attributes.xml b/manifmerger/src/test/java/com/android/manifmerger/data/04_inject_attributes.xml deleted file mode 100755 index 57f4e84..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/04_inject_attributes.xml +++ /dev/null @@ -1,63 +0,0 @@ -# -# Test: -# - Inject attributes in a main manifest. -# The attributes are injected and then the merge is done. In this case the app -# starts with a minSdkVersion of 20, which is higher than the lib1's 15 value. -# However the injection replaces it by 10, which is now lower than the lib's -# version and thus a warning will be generated. -# - -@fails - -@inject -/manifest/uses-sdk|http://schemas.android.com/apk/res/android minSdkVersion=10 -/manifest/uses-sdk|http://schemas.android.com/apk/res/android targetSdkVersion=14 -/manifest/application|http://schemas.android.com/apk/res/android label=null -/manifest/application|http://schemas.android.com/apk/res/android icon=null - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="20" android:targetSdkVersion="21"/> - - <application android:name="com.example.TheApp" /> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="16"/> - - <application android:name="com.example.TheApp" /> - -</manifest> - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14"/> - - <application android:name="com.example.TheApp" /> - -</manifest> - -@errors - -E [ManifestMergerTest0_main.xml:3, ManifestMergerTest1_lib1.xml:3] Main manifest has <uses-sdk android:minSdkVersion='10'> but library uses minSdkVersion='15' -W [ManifestMergerTest0_main.xml:3, ManifestMergerTest1_lib1.xml:3] Main manifest has <uses-sdk android:targetSdkVersion='14'> but library uses targetSdkVersion='16' diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/10_activity_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/10_activity_merge.xml deleted file mode 100755 index 59c5c42..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/10_activity_merge.xml +++ /dev/null @@ -1,378 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that a normal merge is done as expected. -# There's a warning because one of the activities from lib2 is already defined -# in the main but it's purely identical so it's not an error. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- This is exactly the same as in lib2_activity --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - - <!-- When comparing duplicate elements, whitespace and comments are ignored. --> - - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - </activity> - - <!-- end of the main manifest's application element. Note that the - merger will insert at the end of this comment, in the specific - order activity, activity-alias, service, receiver and provider. --> - - </application> - -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name" > - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Activity to configure widget --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <intent-filter > - <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> - </intent-filter> - </activity> - </application> - -</manifest> - - -@lib2_activity - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name" > - - <!-- This won't be merged because there's already an identical definition in the main. --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider android:name=".app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - - <!-- This one does not conflict with the main --> - <activity - android:name="com.example.LibActivity2" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib3_alias - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <!-- This comment is ignored. --> - - <application android:label="@string/lib_name" > - - <!-- The first comment just before the element - is carried over as-is. - --> - <!-- Formatting is preserved. --> - <!-- All consecutive comments are taken together. --> - - <activity-alias - android:name="com.example.alias.MyActivity" - android:targetActivity="com.example.MainActivity" - android:label="@string/alias_name" - android:icon="@drawable/alias_icon" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- This is a dup of the 2nd activity in lib2 --> - <activity - android:name="com.example.LibActivity2" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- This is exactly the same as in lib2_activity --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - - <!-- When comparing duplicate elements, whitespace and comments are ignored. --> - - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - - </activity> - - <!-- end of the main manifest's application element. Note that the - merger will insert at the end of this comment, in the specific - order activity, activity-alias, service, receiver and provider. --> - -# from @lib1_widget - <!-- Activity to configure widget --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <intent-filter > - <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> - </intent-filter> - </activity> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - -# from @lib2_activity - <!-- This one does not conflict with the main --> - <activity - android:name="com.example.LibActivity2" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - -# from @lib3_alias - <!-- The first comment just before the element - is carried over as-is. - --> - <!-- Formatting is preserved. --> - <!-- All consecutive comments are taken together. --> - - <activity-alias - android:name="com.example.alias.MyActivity" - android:targetActivity="com.example.MainActivity" - android:label="@string/alias_name" - android:icon="@drawable/alias_icon" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - </application> - -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:31, ManifestMergerTest2_lib2_activity.xml:6] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element. -P [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Skipping identical /manifest/application/activity[@name=com.example.LibActivity2] element. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/11_activity_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/11_activity_dup.xml deleted file mode 100755 index ef163b0..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/11_activity_dup.xml +++ /dev/null @@ -1,406 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that an error is generated because the libraries define -# activities which are already in the main, with slightly different XML content: -# number and *order* of elements must match, attributes must match. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - - <!-- Conflict with lib1 --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <!-- missing the intent-filter --> - </activity> - - - <!-- Conflict with lib2 --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon"> - <!-- missing attribute android:theme="@style/Lib.Theme" --> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name" > - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Activity to configure widget --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <intent-filter > - <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> - </intent-filter> - </activity> - </application> - -</manifest> - - -@lib2_activity - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name" > - - <!-- This won't be merged because there's already an identical definition in the main. --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider android:name=".app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - - <!-- This one does not conflict with the main --> - <activity - android:name="com.example.LibActivity2" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib3_alias - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <!-- This comment is ignored. --> - - <application android:label="@string/lib_name" > - - <!-- The first comment just before the element - is carried over as-is. - --> - <!-- Formatting is preserved. --> - <!-- All consecutive comments are taken together. --> - - <activity-alias - android:name="com.example.alias.MyActivity" - android:targetActivity="com.example.MainActivity" - android:label="@string/alias_name" - android:icon="@drawable/alias_icon" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- This will conflict with the 2nd one from lib2 --> - <activity - android:name="com.example.LibActivity2" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - <category android:name="android.intent.category.MOARCATZPLZ" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <!-- Typical analytics permissions. --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. --> - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - - <!-- Conflict with lib1 --> - <activity - android:icon="@drawable/widget_icon" - android:label="Configure Widget" - android:name="com.example.WidgetConfigurationUI" - android:theme="@style/Theme.WidgetConfigurationUI" > - <!-- missing the intent-filter --> - </activity> - - - <!-- Conflict with lib2 --> - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon"> - <!-- missing attribute android:theme="@style/Lib.Theme" --> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - -# from @lib1_widget - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService" /> - - <!-- Broadcast Receiver for a widget. --> - <receiver - android:label="@string/widget_name" - android:icon="@drawable/widget_icon" - android:name="com.example.WidgetReceiver" > - <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> - </intent-filter> - <meta-data - android:name="android.appwidget.provider" - android:resource="@xml/widget_provider" - /> - </receiver> - -# from @lib2_activity - <!-- This one does not conflict with the main --> - <activity android:icon="@drawable/lib_activity_icon" android:label="@string/lib_activity_name" android:name="com.example.LibActivity2" android:theme="@style/Lib.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.LAUNCHER"/> - </intent-filter> - </activity> - - <!-- Provider extracted from ApiDemos --> - <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider" - android:authorities="com.example.android.apis.app.LoaderThrottle" - android:enabled="@bool/atLeastHoneycomb" /> - -# from @lib3_alias - <!-- The first comment just before the element - is carried over as-is. - --> - <!-- Formatting is preserved. --> - <!-- All consecutive comments are taken together. --> - - <activity-alias - android:name="com.example.alias.MyActivity" - android:targetActivity="com.example.MainActivity" - android:label="@string/alias_name" - android:icon="@drawable/alias_icon" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - </application> - -</manifest> - - -@errors - -E [ManifestMergerTest0_main.xml:32, ManifestMergerTest1_lib1_widget.xml:16] Trying to merge incompatible /manifest/application/activity[@name=com.example.WidgetConfigurationUI] element: - <activity - @android:name="com.example.WidgetConfigurationUI" ---</activity> ---(end reached) - <activity - @android:name="com.example.WidgetConfigurationUI" -++ <intent-filter> -++ <action -++ @android:name="android.appwidget.action.APPWIDGET_CONFIGURE"> -E [ManifestMergerTest0_main.xml:38, ManifestMergerTest2_lib2_activity.xml:6] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity] element: - <activity --- @android:name="com.example.LibActivity"> --- <intent-filter> --- <action - <activity -++ @android:name="com.example.LibActivity" -++ @android:theme="@style/Lib.Theme"> -++ <intent-filter> -E [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity2] element: - <activity - @android:name="com.example.LibActivity2" - @android:name="android.intent.action.MAIN"> - @android:name="android.intent.category.LAUNCHER"> --- </intent-filter> ---</activity> ---(end reached) - <activity - @android:name="com.example.LibActivity2" - <intent-filter> - @android:name="android.intent.action.MAIN"> - @android:name="android.intent.category.LAUNCHER"> -++ <category -++ @android:name="android.intent.category.MOARCATZPLZ"> -++ </category> diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/12_alias_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/12_alias_dup.xml deleted file mode 100755 index 7b5aed3..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/12_alias_dup.xml +++ /dev/null @@ -1,211 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that an error is generated because the libraries define -# aliases which are already defined differently. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity-alias - android:name="com.example.alias.MyActivity1" - android:targetActivity="com.example.MainActivity1" - android:label="@string/alias_name1" - android:icon="@drawable/alias_icon1" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <activity-alias - android:name="com.example.alias.MyActivity2" - android:targetActivity="com.example.MainActivity2" - android:label="@string/alias_name2" - android:icon="@drawable/alias_icon2" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Same as 1 in main --> - <activity-alias - android:name="com.example.alias.MyActivity1" - android:targetActivity="com.example.MainActivity1" - android:label="@string/alias_name1" - android:icon="@drawable/alias_icon1" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- Differs from 2 in main --> - <activity-alias - android:name="com.example.alias.MyActivity2" - android:targetActivity="com.example.MainActivity2"> - </activity-alias> - - <!-- A new one defined by lib1 --> - <activity-alias - android:name="com.example.alias.MyActivity3" - android:targetActivity="com.example.MainActivity3" - android:label="@string/alias_name3" - android:icon="@drawable/alias_icon3" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - </application> - -</manifest> - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name2" > - - <!-- Conflicts with 3 from lib1 --> - <activity-alias - android:name="com.example.alias.MyActivity3" - android:label="@string/alias_name3" - android:icon="@drawable/alias_icon3"> - <intent-filter> - <category android:name="android.intent.category.LAUNCHER2" /> - </intent-filter> - </activity-alias> - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity-alias - android:name="com.example.alias.MyActivity1" - android:targetActivity="com.example.MainActivity1" - android:label="@string/alias_name1" - android:icon="@drawable/alias_icon1" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <activity-alias - android:name="com.example.alias.MyActivity2" - android:targetActivity="com.example.MainActivity2" - android:label="@string/alias_name2" - android:icon="@drawable/alias_icon2" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- A new one defined by lib1 --> - <activity-alias - android:name="com.example.alias.MyActivity3" - android:targetActivity="com.example.MainActivity3" - android:label="@string/alias_name3" - android:icon="@drawable/alias_icon3" - > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - </application> - -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/activity-alias[@name=com.example.alias.MyActivity1] element. -E [ManifestMergerTest0_main.xml:13, ManifestMergerTest1_lib1.xml:14] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity2] element: - <activity-alias --- @android:icon="@drawable/alias_icon2" --- @android:label="@string/alias_name2" --- @android:name="com.example.alias.MyActivity2" - <activity-alias -++ @android:name="com.example.alias.MyActivity2" -++ @android:targetActivity="com.example.MainActivity2"> -++</activity-alias> -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity3] element: - <activity-alias --- @android:name="com.example.alias.MyActivity3" --- @android:targetActivity="com.example.MainActivity3"> --- <intent-filter> - <activity-alias -++ @android:name="com.example.alias.MyActivity3"> -++ <intent-filter> -++ <category diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/13_service_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/13_service_dup.xml deleted file mode 100755 index 4c257fa..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/13_service_dup.xml +++ /dev/null @@ -1,167 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that an error is generated because the libraries define -# services which are already defined differently. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService1" /> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService2" /> - - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Same as 1 in main --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService1" /> - - <!-- Differs from 2 in main --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService2" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </service> - - <!-- A new one defined by lib1 --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService3" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </service> - - </application> - -</manifest> - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name2" > - - <!-- Conflicts with 3 from lib1 --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService3" /> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService1" /> - - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService2" /> - - <!-- A new one defined by lib1 --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService3" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </service> - - </application> - -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/service[@name=com.example.AppService1] element. -E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService2] element: - <service - @android:name="com.example.AppService2"> ---</service> ---(end reached) - <service - @android:name="com.example.AppService2"> -++ <intent-filter> -++ <action -++ @android:name="android.intent.action.MAIN"> -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService3] element: - <service - @android:name="com.example.AppService3"> --- <intent-filter> --- <action --- @android:name="android.intent.action.MAIN"> - <service - @android:name="com.example.AppService3"> -++</service> -++(end reached) diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/14_receiver_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/14_receiver_dup.xml deleted file mode 100755 index 777ba22..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/14_receiver_dup.xml +++ /dev/null @@ -1,186 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that an error is generated because the libraries define -# receivers which are already defined differently. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <receiver - android:name="com.example.AppReceiver1" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <receiver - android:name="com.example.AppReceiver2" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Same as 1 in main --> - <receiver - android:name="com.example.AppReceiver1" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- Differs from 2 in main --> - <receiver - android:name="com.example.AppReceiver2" /> - - <!-- A new one defined by lib1 --> - <receiver - android:name="com.example.AppReceiver3" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM1" /> - <action android:name="com.example.action.ACTION_CUSTOM2" /> - <action android:name="com.example.action.ACTION_CUSTOM3" /> - </intent-filter> - </receiver> - - </application> - -</manifest> - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name2" > - - <!-- Conflicts with 3 from lib1 --> - <receiver - android:name="com.example.AppReceiver3" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <receiver - android:name="com.example.AppReceiver1" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <receiver - android:name="com.example.AppReceiver2" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- A new one defined by lib1 --> - <receiver - android:name="com.example.AppReceiver3" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM1" /> - <action android:name="com.example.action.ACTION_CUSTOM2" /> - <action android:name="com.example.action.ACTION_CUSTOM3" /> - </intent-filter> - </receiver> - - </application> - -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver1] element. -E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:13] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver2] element: - <receiver --- @android:icon="@drawable/app_icon" --- @android:name="com.example.AppReceiver2"> --- <intent-filter> - <receiver -++ @android:name="com.example.AppReceiver2"> -++</receiver> -++(end reached) -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver3] element: - <receiver - @android:name="com.example.AppReceiver3"> - <intent-filter> - <action --- @android:name="com.example.action.ACTION_CUSTOM1"> - <receiver - @android:name="com.example.AppReceiver3"> - <intent-filter> - <action -++ @android:name="com.example.action.ACTION_CUSTOM"> diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/15_provider_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/15_provider_dup.xml deleted file mode 100755 index bd0c8fe..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/15_provider_dup.xml +++ /dev/null @@ -1,153 +0,0 @@ -# -# Test: -# - Activities from libraries are merged in the main manifest. -# - Acts on activity / activity-alias / service / receiver / provider. -# - Elements are merged as-is with the first comment element preceding them. -# - Whitespace preceding the merged elements is transfered over too. -# -# Note: -# - New elements are always merged at the end of the application element. -# - It's an error if an element with the same @name attribute is defined -# or merged more than once unless the definition is *exactly* the same, -# the "same" being defined by the exact XML elements, whitespace excluded. -# -# This tests that an error is generated because the libraries define -# providers which are already defined differently. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <provider - android:name="com.example.Provider1" - android:authorities="com.example.android.apis.app.thingy1" - android:enabled="@bool/someConditionalValue" /> - - <provider - android:name="com.example.Provider2" /> - - </application> - -</manifest> - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Same as MyActivity1 in main --> - <provider - android:name="com.example.Provider1" - android:authorities="com.example.android.apis.app.thingy1" - android:enabled="@bool/someConditionalValue" /> - - <!-- Differs from MyActivity2 in main --> - <provider - android:name="com.example.Provider2" - android:authorities="com.example.android.apis.app.thingy2" - android:enabled="@bool/someConditionalValue2" /> - - <!-- A new one defined by lib1 --> - <provider - android:name="com.example.Provider3" - android:authorities="com.example.android.apis.app.thingy3" - android:enabled="@bool/someConditionalValue" /> - - </application> - -</manifest> - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name2" > - - <!-- Conflicts with 3 from lib1 --> - <provider - android:name="com.example.Provider3" - android:authorities="com.example.android.apis.app.thingy3" /> - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <provider - android:name="com.example.Provider1" - android:authorities="com.example.android.apis.app.thingy1" - android:enabled="@bool/someConditionalValue" /> - - <provider - android:name="com.example.Provider2" /> - - <!-- A new one defined by lib1 --> - <provider - android:name="com.example.Provider3" - android:authorities="com.example.android.apis.app.thingy3" - android:enabled="@bool/someConditionalValue" /> - - </application> - -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/provider[@name=com.example.Provider1] element. -E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider2] element: - <provider --- @android:name="com.example.Provider2"> ---</provider> ---(end reached) - <provider -++ @android:authorities="com.example.android.apis.app.thingy2" -++ @android:enabled="@bool/someConditionalValue2" -++ @android:name="com.example.Provider2"> -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider3] element: - <provider --- @android:enabled="@bool/someConditionalValue" --- @android:name="com.example.Provider3"> ---</provider> - <provider -++ @android:name="com.example.Provider3"> -++</provider> -++(end reached) diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/16_fqcn_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/16_fqcn_merge.xml deleted file mode 100755 index 8414a3c..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/16_fqcn_merge.xml +++ /dev/null @@ -1,129 +0,0 @@ -# -# Test how FQCN class names are expanded and handled: -# - A library application can be merged doesn't have an app class name. -# - A library application can be merged if it has the same class name as the app. -# - A partial class name is expanded using the package name in a library or app. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - </application> -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:name="com.example.app1.TheApp" > - <activity android:name=".WidgetLibrary" /> - <receiver android:name=".WidgetReceiver" /> - <service android:name="AppService" /> - <activity android:name="com.example.lib1.WidgetConfigurationUI" /> - </application> -</manifest> - - -@lib2_activity - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application> - <!-- This won't be merged because there's already an identical definition in the main. --> - <activity android:name="LibActivity" /> - - <!-- Provider extracted from ApiDemos --> - <provider android:name=".app.LoaderThrottle$SimpleProvider" /> - - <!-- This one does not conflict with the main --> - <activity android:name="com.example.lib2.LibActivity2" /> - - </application> -</manifest> - - -@lib3_alias - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3" > - <!-- This manifest has a 'package' attribute and FQCNs get resolved. --> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent"> - <activity-alias android:name="com.example.lib3.MyActivity" - android:targetActivity="com.example.app1.MainActivity" /> - - <!-- This is a dup of the 2nd activity in lib2 --> - <activity android:name="com.example.lib2.LibActivity2" /> - - <!-- These class name should be expanded. --> - <activity android:name=".LibActivity3" /> - <service android:name=".LibService3" /> - <receiver android:name=".LibReceiver3" /> - <provider android:name=".LibProvider3" /> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> -# from @lib1_widget - <activity android:name="com.example.lib1.WidgetLibrary" /> - <activity android:name="com.example.lib1.WidgetConfigurationUI" /> - <service android:name="com.example.lib1.AppService" /> - <receiver android:name="com.example.lib1.WidgetReceiver" /> - -# from @lib2_activity - <!-- This one does not conflict with the main --> - <activity android:name="com.example.lib2.LibActivity2" /> - - <!-- Provider extracted from ApiDemos --> - <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider" /> - -# from @lib3_alias - <!-- These class name should be expanded. --> - <activity android:name="com.example.lib3.LibActivity3" /> - <activity-alias android:name="com.example.lib3.MyActivity" - android:targetActivity="com.example.app1.MainActivity" /> - <service android:name="com.example.lib3.LibService3" /> - <receiver android:name="com.example.lib3.LibReceiver3" /> - <provider android:name="com.example.lib3.LibProvider3" /> - </application> -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest2_lib2_activity.xml:5] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity] element. -P [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:8] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity2] element. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/17_fqcn_conflict.xml b/manifmerger/src/test/java/com/android/manifmerger/data/17_fqcn_conflict.xml deleted file mode 100755 index b4f5ea0..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/17_fqcn_conflict.xml +++ /dev/null @@ -1,120 +0,0 @@ -# -# Test how FQCN class names are expanded and handled: -# - A library application can be merged doesn't have an app class name. -# - A library application can be merged if it has the same class name as the app. -# - A partial class name is expanded using the package name in a library or app. -# -# All tests fail with just warnings, no solid errors. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - </application> -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- App name is different, will not merge. --> - <application android:name="TheApp" > - <activity android:name=".WidgetLibrary1" /> - </application> -</manifest> - - -@lib2_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- App name is good, but backupAgent is mentioned and is different, will not merge. --> - <application - android:name="com.example.app1.TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".WidgetLibrary2" /> - <activity android:name=".LibActivity" /> - </application> -</manifest> - - -@lib3_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <application android:name="com.example.app1.TheApp"> - <activity android:name=".WidgetLibrary3" /> - </application> - -</manifest> - - -@lib4_not_package - -<manifest xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- It's an error for the manifest to lack a 'package' attribute. - We just emit a warning in this case. - --> - - <application> - <!-- These class name can't be expanded due to the lack of 'package' attribute. --> - <activity android:name=".LibActivity4" /> - <service android:name=".LibService4" /> - <receiver android:name=".LibReceiver4" /> - <provider android:name=".LibProvider4" /> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - <activity android:name="com.example.lib1.WidgetLibrary1" /> - <activity android:name="com.example.lib2.WidgetLibrary2" /> - <activity android:name="com.example.lib3.WidgetLibrary3" /> -# from @lib4_alias - <!-- These class name can't be expanded due to the lack of 'package' attribute. --> - <activity android:name=".LibActivity4" /> - <service android:name=".LibService4" /> - <receiver android:name=".LibReceiver4" /> - <provider android:name=".LibProvider4" /> - </application> -</manifest> - -@errors - -W [ManifestMergerTest0_main.xml:3, ManifestMergerTest1_lib1_widget.xml:4] Main manifest has <application android:name='com.example.app1.TheApp'> but library uses name='com.example.lib1.TheApp'. -W [ManifestMergerTest0_main.xml:3, ManifestMergerTest2_lib2_widget.xml:4] Main manifest has <application android:backupAgent='com.example.app1.MyBackupAgent'> but library uses backupAgent='com.example.lib2.MyBackupAgent'. -P [ManifestMergerTest0_main.xml:6, ManifestMergerTest2_lib2_widget.xml:6] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity] element. -W [ManifestMergerTest4_lib4_not_package.xml:1] Missing 'package' attribute in manifest. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/20_uses_lib_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/20_uses_lib_merge.xml deleted file mode 100755 index a5eecce..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/20_uses_lib_merge.xml +++ /dev/null @@ -1,176 +0,0 @@ -# -# Test merge of uses-library: -# - Merge is OK if destination already has one with the same @name. -# - required defaults to "true" -# - when merging, a required=true (explicit or implicit) overwrites a required=false. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary0_DefaultTrue" /> - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary1_DefaultTrue" /> - - <!-- A library that is explicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary2_RequiredTrue" - android:required="true" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="false" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Same as 1 from main, marking it as required=false --> - <uses-library - android:name="com.example.SomeLibrary1_DefaultTrue" - android:required="false" /> - - <!-- Same as 3 from main --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="false" /> - - <!-- Same as 4 from main --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - <!-- Add a new lib that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary5_RequiredTrue" - android:required="true" /> - - <!-- Add a new lib that is implicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" - android:required="false" /> - - </application> -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name1" > - - <!-- Overrides 3, changing it from required=false to true --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="true" /> - - <!-- Same as 4 from main --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - <!-- Overrides 6, but implicitly declaring required=True --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" /> - - </application> -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary0_DefaultTrue" /> - - <!-- A library that is implicitly marked as required=true --> -# required=false from lib1 is ignored, it stays at the default - <uses-library - android:name="com.example.SomeLibrary1_DefaultTrue" /> - - <!-- A library that is explicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary2_RequiredTrue" - android:required="true" /> - - <!-- A library that is explicitly marked as required=false --> -# lib1 keeps it required=false but lib2 makes it switch to required=true - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="true" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - -# new from lib1 - <!-- Add a new lib that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary5_RequiredTrue" - android:required="true" /> - -# new from lib1, but lib2 makes it switch to required=true - <!-- Add a new lib that is implicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" - android:required="true" /> - - </application> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/21_uses_lib_errors.xml b/manifmerger/src/test/java/com/android/manifmerger/data/21_uses_lib_errors.xml deleted file mode 100755 index 9e8f5a0..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/21_uses_lib_errors.xml +++ /dev/null @@ -1,202 +0,0 @@ -# -# Test merge of uses-library: -# - Merge is OK if destination already has one with the same @name. -# - required defaults to "true" -# - when merging, a required=true (explicit or implicit) overwrites a required=false. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary0_DefaultTrue" /> - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary1_DefaultTrue" /> - - <!-- A library that is explicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary2_RequiredTrue" - android:required="booh!" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="false" /> - - <!-- A library that is explicitly marked as required=false. Duplicated. --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="false" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <application android:label="@string/lib_name1" > - - <!-- Error: android:name attribute is missing. --> - <uses-library /> - <uses-library android:required="false" /> - <uses-library android:required="true" /> - - <!-- Same as 2 from main. Warning/ignore because dest required isn't true/false. --> - <uses-library - android:name="com.example.SomeLibrary2_RequiredTrue" - android:required="true" /> - - <!-- Same as 3 from main. Warning because destination has a duplicate. --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="false" /> - - <!-- Same as 4 from main. Warning because required isn't true or false. --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="foo" /> - - <!-- Add a new lib that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary5_RequiredTrue" - android:required="true" /> - - <!-- Add a new lib that is implicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" - android:required="false" /> - - </application> -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application android:label="@string/lib_name1" > - - <!-- Overrides 3, changing it from required=false to true --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="true" /> - - <!-- Same as 4 from main --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - <!-- Overrides 6, but implicitly declaring required=True --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" /> - - </application> -</manifest> - - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary0_DefaultTrue" /> - - <!-- A library that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary1_DefaultTrue" /> - - <!-- A library that is explicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary2_RequiredTrue" - android:required="booh!" /> - - <!-- A library that is explicitly marked as required=false --> -# lib1 keeps it required=false but lib2 makes it switch to required=true - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="true" /> - - <!-- A library that is explicitly marked as required=false. Duplicated. --> - <uses-library - android:name="com.example.SomeLibrary3_RequiredFalse" - android:required="true" /> - - <!-- A library that is explicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - -# new from lib1 - <!-- Add a new lib that is implicitly marked as required=true --> - <uses-library - android:name="com.example.SomeLibrary5_RequiredTrue" - android:required="true" /> - -# new from lib1, but lib2 makes it switch to required=true - <!-- Add a new lib that is implicitly marked as required=false --> - <uses-library - android:name="com.example.SomeLibrary6_RequiredFalse" - android:required="true" /> - - </application> - -</manifest> - - -@errors - -E [ManifestMergerTest1_lib1.xml:6] Undefined 'name' attribute in /manifest/application/uses-library. -E [ManifestMergerTest1_lib1.xml:7] Undefined 'name' attribute in /manifest/application/uses-library. -E [ManifestMergerTest1_lib1.xml:8] Undefined 'name' attribute in /manifest/application/uses-library. -W [ManifestMergerTest0_main.xml:12] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary2_RequiredTrue] element: -Expected 'true' or 'false' but found 'booh!'. -W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. -W [ManifestMergerTest1_lib1.xml:17] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary4_RequiredFalse] element: -Expected 'true' or 'false' but found 'foo'. -W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/25_permission_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/25_permission_merge.xml deleted file mode 100755 index 07208ad..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/25_permission_merge.xml +++ /dev/null @@ -1,259 +0,0 @@ -# -# Text permission, permission-group and permission-tree: -# - Libraries can add any of these elements as long as they don't conflict -# with the destination: either the element must not be at all in the destination -# (as identified by the name) or it must match exactly. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Same permissions as main manifest --> - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <!-- Added by lib1. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="normal" /> - - <permission-group - android:description="This is getting" - android:label="too silly" - android:name="com.example.EnoughWithTheQuotes" /> - - <permission-tree - android:name="com.example.PermTree1" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Redefine one permission from main manifest --> - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - <!-- And one from lib1. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="normal" /> - <permission-tree - android:name="com.example.PermTree1" /> - - <!-- Added by lib2. --> - <permission - android:name="com.example.SensiblePermission2" - android:permissionGroup="com.example.SensibleGroup2" - android:protectionLevel="normal" /> - - <permission-group - android:name="com.example.SensibleGroup2" /> - - <permission-tree - android:name="com.example.PermTree2" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -# Added by lib1 - <!-- Added by lib1. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="normal" /> - - <permission-group - android:description="This is getting" - android:label="too silly" - android:name="com.example.EnoughWithTheQuotes" /> - - <permission-tree - android:name="com.example.PermTree1" /> - -# Added by lib2 - <!-- Added by lib2. --> - <permission - android:name="com.example.SensiblePermission2" - android:permissionGroup="com.example.SensibleGroup2" - android:protectionLevel="normal" /> - - <permission-group - android:name="com.example.SensibleGroup2" /> - - <permission-tree - android:name="com.example.PermTree2" /> - -</manifest> - - -@errors diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/26_permission_dup.xml b/manifmerger/src/test/java/com/android/manifmerger/data/26_permission_dup.xml deleted file mode 100755 index bd9a4f1..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/26_permission_dup.xml +++ /dev/null @@ -1,314 +0,0 @@ -# -# Text permission, permission-group and permission-tree: -# - Libraries can add any of these elements as long as they don't conflict -# with the destination: either the element must not be at all in the destination -# (as identified by the name) or it must match exactly. -# -# This one tests that duplicate definitions that are strictly equal generate errors -# with some (hopefully useful) diff. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Similar permissions as main manifest, but with slight conflicts --> - <permission - android:description="Different description here" - android:icon="@drawable/not_the_same_icon" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - <!-- missing icon: --><permission-group - android:description="Nobody expects..." - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - <permission-tree - android:label="This is not the same label" - android:name="com.example.PermTree" /> - - <!-- different protectionLevel --><permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="normal" /> - - <!-- Added by lib1. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="normal" /> - - <permission-group - android:description="This is getting" - android:label="too silly" - android:name="com.example.EnoughWithTheQuotes" /> - - <permission-tree - android:name="com.example.PermTree1" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Redefine one permission from main manifest --> - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - <!-- And one from lib1, with a slight variation. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="system" /> - <permission-tree - android:description="Extra description" - android:name="com.example.PermTree1" /> - - <!-- Added by lib2. --> - <permission - android:name="com.example.SensiblePermission2" - android:permissionGroup="com.example.SensibleGroup2" - android:protectionLevel="normal" /> - - <permission-group - android:name="com.example.SensibleGroup2" /> - - <permission-tree - android:name="com.example.PermTree2" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -# Added by lib1 - <!-- Added by lib1. --> - <permission - android:name="com.example.Permission1" - android:permissionGroup="com.example.Permission1" - android:protectionLevel="normal" /> - - <permission-group - android:description="This is getting" - android:label="too silly" - android:name="com.example.EnoughWithTheQuotes" /> - - <permission-tree - android:name="com.example.PermTree1" /> - -# Added by lib2 - <!-- Added by lib2. --> - <permission - android:name="com.example.SensiblePermission2" - android:permissionGroup="com.example.SensibleGroup2" - android:protectionLevel="normal" /> - - <permission-group - android:name="com.example.SensibleGroup2" /> - - <permission-tree - android:name="com.example.PermTree2" /> - -</manifest> - - -@errors - -E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:4] Trying to merge incompatible /manifest/permission[@name=com.example.DangerWillRobinson] element: - <permission --- @android:description="Insert boring description here" --- @android:icon="@drawable/robot" - <permission -++ @android:description="Different description here" -++ @android:icon="@drawable/not_the_same_icon" -E [ManifestMergerTest0_main.xml:14, ManifestMergerTest1_lib1.xml:8] Trying to merge incompatible /manifest/permission[@name=com.example.WhatWereYouThinking] element: - <permission - @android:name="com.example.WhatWereYouThinking" --- @android:protectionLevel="signatureOrSystem"> - <permission - @android:name="com.example.WhatWereYouThinking" -++ @android:protectionLevel="normal"> -E [ManifestMergerTest0_main.xml:16, ManifestMergerTest1_lib1.xml:5] Trying to merge incompatible /manifest/permission-group[@name=com.example.MasterControlPermission] element: - <permission-group --- @android:icon="@drawable/ignored_icon" --- @android:label="the Spanish Inquisition" --- @android:name="com.example.MasterControlPermission"> - <permission-group -++ @android:label="the Spanish Inquisition" -++ @android:name="com.example.MasterControlPermission"> -++</permission-group> -E [ManifestMergerTest0_main.xml:18, ManifestMergerTest1_lib1.xml:6] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree] element: - <permission-tree --- @android:label="This is not a label" - <permission-tree -++ @android:label="This is not the same label" -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/permission[@name=com.example.Permission1] element: - <permission - @android:name="com.example.Permission1" --- @android:protectionLevel="normal"> - <permission - @android:name="com.example.Permission1" -++ @android:protectionLevel="system"> -E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:7] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree1] element: - <permission-tree --- @android:name="com.example.PermTree1"> ---</permission-tree> ---(end reached) - <permission-tree -++ @android:description="Extra description" -++ @android:name="com.example.PermTree1"> -++</permission-tree> diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/28_uses_perm_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/28_uses_perm_merge.xml deleted file mode 100755 index ecc644a..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/28_uses_perm_merge.xml +++ /dev/null @@ -1,156 +0,0 @@ -# -# Text uses-permission: -# - Libraries can add any of these elements as long as they don't conflict -# with the destination: either the element must not be at all in the destination -# (as identified by the name) or it must match exactly. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Same permissions as main manifest --> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <!-- Library 1 wants to know what you're running. --> - <uses-permission android:name="android.permission.GET_TASKS" /> - - <!-- Are you calling me? --> - <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Redefine one permission from main manifest --> - <uses-permission android:name="android.permission.INTERNET" /> - <!-- And one from lib1. --> - <uses-permission android:name="android.permission.GET_TASKS" /> - - <!-- Lib2 wants to know it all. --> - <uses-permission android:name="android.permission.READ_LOGS"/> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -# Added by lib1 - <!-- Library 1 wants to know what you're running. --> - <uses-permission android:name="android.permission.GET_TASKS" /> - - <!-- Are you calling me? --> - <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - -# Added by lib2 - <!-- Lib2 wants to know it all. --> - <uses-permission android:name="android.permission.READ_LOGS"/> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/30_uses_sdk_ok.xml b/manifmerger/src/test/java/com/android/manifmerger/data/30_uses_sdk_ok.xml deleted file mode 100755 index bcee4ce..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/30_uses_sdk_ok.xml +++ /dev/null @@ -1,86 +0,0 @@ -# -# Test uses-sdk: add a uses-sdk from an app that doesn't define one. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="14" - /> - - <application /> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- This app requires cupcake. --> - <uses-sdk android:minSdkVersion="3" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- This only defines a max-sdk, and we purposely ignore this attribute. - It doesn't get merged and doesn't generate a conflict either. - --> - <uses-sdk - android:maxSdkVersion="5" - /> - -</manifest> - - -@lib3 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <!-- Lib3 redefines the same requirements as lib1. - --> - <uses-sdk - android:minSdkVersion="3" - android:targetSdkVersion="11" - /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="14" - /> - - <application /> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml b/manifmerger/src/test/java/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml deleted file mode 100755 index b94efe8..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml +++ /dev/null @@ -1,70 +0,0 @@ -# -# Test uses-sdk: it's ok for a library to have a smaller minSdkVersion than the main manifest. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="14" /> - - <application /> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- it's ok for a library to have a smaller minSdkVersion than the main manifest. --> - <uses-sdk android:minSdkVersion="4" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <uses-sdk android:minSdkVersion="10" /> - -</manifest> - - -@lib3 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <uses-sdk android:minSdkVersion="11" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="14" /> - - <application /> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml b/manifmerger/src/test/java/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml deleted file mode 100755 index 8edbedb..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml +++ /dev/null @@ -1,148 +0,0 @@ -# -# Test uses-sdk: it's an error for a library to require a minSdkVersion higher than the -# one defined in the main manifest. -# -# Also a uses-sdk with a lack of minSdkVersion is equivalent to using version=1. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - <uses-sdk android:targetSdkVersion="14" /> - - <application /> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- The app can cope with API 1 but this library can only cope with API 4. --> - <uses-sdk android:minSdkVersion="4" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <uses-sdk android:minSdkVersion="10" /> - -</manifest> - - -@lib3 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <uses-sdk android:minSdkVersion="11" /> - -</manifest> - - -@lib4_parsingError - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib4"> - - <!-- Parsing errors --> - <uses-sdk android:minSdkVersion="abcd" /> - -</manifest> - - -@lib5_parsingError - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib5"> - - <!-- Parsing errors --> - <uses-sdk android:minSdkVersion="123456789123456789" /> - -</manifest> - - -@lib6_parsingError - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib6"> - - <!-- Parsing errors --> - <uses-sdk android:minSdkVersion="0xFFFFFFFFFFFFFFFF" /> - -</manifest> - - -@lib7_parsingError - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib7"> - - <!-- Parsing errors --> - <uses-sdk android:minSdkVersion="InvalidMinSdk" android:targetSdkVersion="InvalidTargetSdk" /> - -</manifest> - - -@lib8_parsingCodename - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib8"> - - <!-- Test code names --> - <uses-sdk android:minSdkVersion="ApiCodename1" android:targetSdkVersion="ApiCodename10" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - <uses-sdk android:targetSdkVersion="14" /> - - <application /> - -</manifest> - - -@errors - -E [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='4' -Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. -E [ManifestMergerTest0_main.xml:4, ManifestMergerTest2_lib2.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='10' -Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. -E [ManifestMergerTest0_main.xml:4, ManifestMergerTest3_lib3.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='11' -Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. -E [ManifestMergerTest4_lib4_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='abcd'>: must be an integer number or codename. -E [ManifestMergerTest5_lib5_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='123456789123456789'>: must be an integer number or codename. -E [ManifestMergerTest6_lib6_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='0xFFFFFFFFFFFFFFFF'>: must be an integer number or codename. -E [ManifestMergerTest7_lib7_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='InvalidMinSdk'>: must be an integer number or codename. -E [ManifestMergerTest7_lib7_parsingError.xml:4] Failed to parse <uses-sdk targetSdkVersion='InvalidTargetSdk'>: must be an integer number or codename. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml b/manifmerger/src/test/java/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml deleted file mode 100755 index df8b717..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml +++ /dev/null @@ -1,77 +0,0 @@ -# -# Test uses-sdk: there's a warning if the main manifest defines a targetSdkVersion that -# is smaller than what the libraries target. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This app requires cupcake and targets at least 10. --> - <uses-sdk - android:minSdkVersion="3" - android:targetSdkVersion="ApiCodename10" - /> - - <application /> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- This lib requires cupcake and targets 11 which is > 10 so it's a warning. --> - <uses-sdk - android:minSdkVersion="3" - android:targetSdkVersion="11" - /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- This is not an error nor a warning. --> - <uses-sdk - android:minSdkVersion="3" - android:targetSdkVersion="4" - /> -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This app requires cupcake and targets at least 10. --> - <uses-sdk - android:minSdkVersion="3" - android:targetSdkVersion="ApiCodename10" - /> - - <application /> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:targetSdkVersion='10'> but library uses targetSdkVersion='11' diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/40_uses_feat_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/40_uses_feat_merge.xml deleted file mode 100755 index d14dcaa..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/40_uses_feat_merge.xml +++ /dev/null @@ -1,178 +0,0 @@ -# -# Test merge of uses-feature: -# - Merge is OK if destination already has one with the same @name. -# - required defaults to "true" -# - when merging, a required=true (explicit or implicit) overwrites a required=false. -# -# Note: uses-feature with android:glEsVersion is dealt with in another test case. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature0_DefaultTrue" /> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature1_DefaultTrue" /> - - <!-- A feature that is explicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature2_RequiredTrue" - android:required="true" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="false" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Same as 1 from main, marking it as required=false --> - <uses-feature - android:name="com.example.SomeFeature1_DefaultTrue" - android:required="false" /> - - <!-- Same as 3 from main --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="false" /> - - <!-- Same as 4 from main --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <!-- Add a new feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature5_RequiredTrue" - android:required="true" /> - - <!-- Add a new feature that is implicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" - android:required="false" /> - - <application android:label="@string/lib_name1" > - - </application> -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Overrides 3, changing it from required=false to true --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="true" /> - - <!-- Same as 4 from main --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <!-- Overrides 6, but implicitly declaring required=True --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" /> - - <application android:label="@string/lib_name2" > - - </application> -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature0_DefaultTrue" /> - - <!-- A feature that is implicitly marked as required=true --> -# required=false from lib1 is ignored, it stays at the default - <uses-feature - android:name="com.example.SomeFeature1_DefaultTrue" /> - - <!-- A feature that is explicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature2_RequiredTrue" - android:required="true" /> - - <!-- A feature that is explicitly marked as required=false --> -# lib1 keeps it required=false but lib2 makes it switch to required=true - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="true" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -# new from lib1 - <!-- Add a new feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature5_RequiredTrue" - android:required="true" /> - -# new from lib1, but lib2 makes it switch to required=true - <!-- Add a new feature that is implicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" - android:required="true" /> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/41_uses_feat_errors.xml b/manifmerger/src/test/java/com/android/manifmerger/data/41_uses_feat_errors.xml deleted file mode 100755 index b86f74a..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/41_uses_feat_errors.xml +++ /dev/null @@ -1,205 +0,0 @@ -# -# Test merge of uses-feature: -# - Merge is OK if destination already has one with the same @name. -# - required defaults to "true" -# - when merging, a required=true (explicit or implicit) overwrites a required=false. -# -# Note: uses-feature with android:glEsVersion is dealt with in another test case. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature0_DefaultTrue" /> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature1_DefaultTrue" /> - - <!-- A feature that is explicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature2_RequiredTrue" - android:required="booh!" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="false" /> - - <!-- A feature that is explicitly marked as required=false. Duplicated. --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="false" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Error: android:name attribute is missing. --> - <uses-feature /> - <uses-feature android:required="false" /> - <uses-feature android:required="true" /> - - <!-- Same as 2 from main. Warning/ignore because dest required isn't true/false. --> - <uses-feature - android:name="com.example.SomeFeature2_RequiredTrue" - android:required="true" /> - - <!-- Same as 3 from main. Warning because destination as a duplicate. --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="false" /> - - <!-- Same as 4 from main. Warning because required isn't true or false. --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="foo" /> - - <!-- Add a new feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature5_RequiredTrue" - android:required="true" /> - - <!-- Add a new feature that is implicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" - android:required="false" /> - - <application android:label="@string/lib_name1" > - - </application> -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Overrides 3, changing it from required=false to true --> - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="true" /> - - <!-- Same as 4 from main --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <!-- Overrides 6, but implicitly declaring required=True --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" /> - - <application android:label="@string/lib_name2" > - - </application> -</manifest> - - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature0_DefaultTrue" /> - - <!-- A feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature1_DefaultTrue" /> - - <!-- A feature that is explicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature2_RequiredTrue" - android:required="booh!" /> - - <!-- A feature that is explicitly marked as required=false --> -# lib1 keeps it required=false but lib2 makes it switch to required=true - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="true" /> - - <!-- A feature that is explicitly marked as required=false. Duplicated. --> -# in case of duplicated name, they are all modified. - <uses-feature - android:name="com.example.SomeFeature3_RequiredFalse" - android:required="true" /> - - <!-- A feature that is explicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature4_RequiredFalse" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -# new from lib1 - <!-- Add a new feature that is implicitly marked as required=true --> - <uses-feature - android:name="com.example.SomeFeature5_RequiredTrue" - android:required="true" /> - -# new from lib1, but lib2 makes it switch to required=true - <!-- Add a new feature that is implicitly marked as required=false --> - <uses-feature - android:name="com.example.SomeFeature6_RequiredFalse" - android:required="true" /> - -</manifest> - - -@errors - -E [ManifestMergerTest1_lib1.xml:4] Undefined 'name' attribute in /manifest/uses-feature. -E [ManifestMergerTest1_lib1.xml:5] Undefined 'name' attribute in /manifest/uses-feature. -E [ManifestMergerTest1_lib1.xml:6] Undefined 'name' attribute in /manifest/uses-feature. -W [ManifestMergerTest0_main.xml:10] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature2_RequiredTrue] element: -Expected 'true' or 'false' but found 'booh!'. -W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. -W [ManifestMergerTest1_lib1.xml:15] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature4_RequiredFalse] element: -Expected 'true' or 'false' but found 'foo'. -W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/45_uses_feat_gles_once.xml b/manifmerger/src/test/java/com/android/manifmerger/data/45_uses_feat_gles_once.xml deleted file mode 100755 index 57937a6..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/45_uses_feat_gles_once.xml +++ /dev/null @@ -1,126 +0,0 @@ -# -# Test merge of uses-feature with android:glEsVersion: -# - Error if defined in lib+dest with dest < lib. -# - Never automatically change dest. -# - Default implied value is 1.0 (0x00010000). -# -# This tests a case that works. Also checks that glEsVersion attributes are stripped -# when merging uses-feature with the name attribute. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-feature - android:name="com.example.SomeFeature0" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="false" /> - <uses-feature android:glEsVersion="0x00020001" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Add a new feature with a glEsVersion of 2.1 --> - <uses-feature - android:name="com.example.SomeFeature5" - android:required="false" - android:glEsVersion="0x00020001" - /> - - <!-- Add a glEsVersion of 2.0, which will be ignored --> - <uses-feature - android:glEsVersion="0x00020000" - /> - - <application android:label="@string/lib_name1" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored --> - <uses-feature - android:name="com.example.SomeFeature6" - android:required="false" - android:glEsVersion="0x00020001" - /> - - <!-- Add a glEsVersion of 1.0, which will be ignored --> - <uses-feature android:glEsVersion="0x00010000" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-feature - android:name="com.example.SomeFeature0" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="false" /> - <uses-feature android:glEsVersion="0x00020001" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - - <!-- Add a new feature with a glEsVersion of 2.1 --> -# lib1 adds this new node. Note how the glEsVersion=2.1 is stripped out. - <uses-feature - android:name="com.example.SomeFeature5" - android:required="false" - /> - - <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored --> -# lib2 adds this new node. Note how the glEsVersion=2.0 is stripped out. - <uses-feature - android:name="com.example.SomeFeature6" - android:required="false" - /> - -</manifest> - - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml b/manifmerger/src/test/java/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml deleted file mode 100755 index 936d009..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml +++ /dev/null @@ -1,162 +0,0 @@ -# -# Test merge of uses-feature with android:glEsVersion: -# - Error if defined in lib+dest with dest < lib. -# - Never automatically change dest. -# - Default implied value is 1.0 (0x00010000). -# -# This tests a case that doesn't works because the main manifest doesn't declare -# the value and thus defaults to 1.0, so libraries with higher requirements will -# conflict. -# - -@fails - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-feature - android:name="com.example.SomeFeature0" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Add a new feature with a glEsVersion of 2.1 --> - <uses-feature - android:name="com.example.SomeFeature5" - android:required="false" - android:glEsVersion="0x00020001" - /> - - <!-- Add a glEsVersion of 2.0, which will be ignored --> - <uses-feature - android:glEsVersion="0x00020000" - /> - - <application android:label="@string/lib_name1" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored --> - <uses-feature - android:name="com.example.SomeFeature6" - android:required="false" - android:glEsVersion="0x00020001" - /> - - <!-- Add a glEsVersion of 1.0, which will be ignored --> - <uses-feature - android:glEsVersion="0x00010000" - /> - - <!-- Test some invalid values. --> - - <!-- 0 isn't a valid value and generates a warning stating it's ignored. --> - <uses-feature - android:glEsVersion="0" - /> - - <!-- 0.0xFFFF is 0.99... and generates a warning stating it's ignored. - The real minimal value is 1.0, not 0.99... --> - <uses-feature - android:glEsVersion="0x0000FFFF" - /> - - <!-- 0xFFFF.xFFFF is not invalid. It does correspond to 65535.9999847412109375 - which is unlikely to be valid anyway. It's not ignored and should parse just fine. - --> - <uses-feature - android:glEsVersion="0xFFFFFFFF" - /> - - <!-- This value shouldn't parse correctly with a Long and will generate a parsing error. - --> - <uses-feature - android:glEsVersion="0xFFFFFFFFFFFFFFFF" - /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-feature - android:name="com.example.SomeFeature0" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="false" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - </application> - - <!-- Add a new feature with a glEsVersion of 2.1 --> -# lib1 adds this new node. Note how the glEsVersion=2.1 is stripped out. - <uses-feature - android:name="com.example.SomeFeature5" - android:required="false" - /> - - <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored --> -# lib2 adds this new node. Note how the glEsVersion=2.0 is stripped out. - <uses-feature - android:name="com.example.SomeFeature6" - android:required="false" - /> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0x00020001' -Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000. -W [ManifestMergerTest2_lib2.xml:12] Ignoring <uses-feature android:glEsVersion='0'> because it's smaller than 1.0. -W [ManifestMergerTest2_lib2.xml:15] Ignoring <uses-feature android:glEsVersion='0x0000FFFF'> because it's smaller than 1.0. -E [ManifestMergerTest2_lib2.xml:21] Failed to parse <uses-feature android:glEsVersion='0xFFFFFFFFFFFFFFFF'>: must be an integer in the form 0x00020001. -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:18] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0xffffffff' -Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/50_uses_conf_warning.xml b/manifmerger/src/test/java/com/android/manifmerger/data/50_uses_conf_warning.xml deleted file mode 100755 index b1cb3f9..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/50_uses_conf_warning.xml +++ /dev/null @@ -1,162 +0,0 @@ -# -# Test uses-configuration: -# - it's OK if a library defines one or multiple times an element already in the application. -# - it's a warning if the library defines an element not in the application. -# - this does not actually merge anything. The XML is not changed at all. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- this is the same uses-conf than in the main. --> - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- this is the not same uses-conf than in the main. --> - <uses-configuration - android:reqFiveWayNav="false" - android:reqNavigation="trackball" - android:reqTouchScreen="finger" /> - -</manifest> - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/uses-configuration defined in library, missing from main manifest: -<uses-configuration> - @android:reqFiveWayNav = false - @android:reqNavigation = trackball - @android:reqTouchScreen = finger diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/52_support_screens_warning.xml b/manifmerger/src/test/java/com/android/manifmerger/data/52_support_screens_warning.xml deleted file mode 100755 index 363fb2b..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/52_support_screens_warning.xml +++ /dev/null @@ -1,162 +0,0 @@ -# -# Test supports-screens: -# - it's OK if a library defines one or multiple times an element already in the application. -# - it's a warning if the library defines an element not in the application. -# - this does not actually merge anything. The XML is not changed at all. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- this is the same supports-screens than in the main. --> - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- this is the not same supports-screens than in the main. --> - <supports-screens - android:smallScreens="false" - android:resizeable="false" - /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-screens defined in library, missing from main manifest: -<supports-screens> - @android:resizeable = false - @android:smallScreens = false diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/54_compat_screens_warning.xml b/manifmerger/src/test/java/com/android/manifmerger/data/54_compat_screens_warning.xml deleted file mode 100755 index 1e1c2d2..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/54_compat_screens_warning.xml +++ /dev/null @@ -1,204 +0,0 @@ -# -# Test compatible-screens: -# - it's OK if a library defines one or multiple times an element already in the application. -# - it's a warning if the library defines an element not in the application. -# - this does not actually merge anything. The XML is not changed at all. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <compatible-screens> - <screen android:screenSize="small" android:screenDensity="ldpi" /> - <screen android:screenSize="normal" android:screenDensity="xhdpi" /> - </compatible-screens> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- this is the same compatible-screens than in the main. --> - <compatible-screens> - <screen android:screenSize="small" android:screenDensity="ldpi" /> - <screen android:screenSize="normal" android:screenDensity="xhdpi" /> - </compatible-screens> - - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- this is the not same compatible-screens than in the main. --> - <compatible-screens> - <screen android:screenSize="small" android:screenDensity="ldpi" /> - <screen android:screenSize="normal" android:screenDensity="mdpi" /> - </compatible-screens> - - <compatible-screens> - <screen android:screenSize="small" android:screenDensity="ldpi" /> - </compatible-screens> - - <compatible-screens> - <screen android:screenSize="normal" android:screenDensity="ldpi" /> - <screen android:screenSize="normal" android:screenDensity="mdpi" /> - <screen android:screenSize="normal" android:screenDensity="hdpi" /> - <screen android:screenSize="normal" android:screenDensity="xhdpi" /> - </compatible-screens> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <compatible-screens> - <screen android:screenSize="small" android:screenDensity="ldpi" /> - <screen android:screenSize="normal" android:screenDensity="xhdpi" /> - </compatible-screens> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/compatible-screens defined in library, missing from main manifest: -<compatible-screens> - <screen> - @android:screenDensity = ldpi - @android:screenSize = small - <screen> - @android:screenDensity = mdpi - @android:screenSize = normal -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:9] /manifest/compatible-screens defined in library, missing from main manifest: -<compatible-screens> - <screen> - @android:screenDensity = ldpi - @android:screenSize = small -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:13] /manifest/compatible-screens defined in library, missing from main manifest: -<compatible-screens> - <screen> - @android:screenDensity = ldpi - @android:screenSize = normal - <screen> - @android:screenDensity = mdpi - @android:screenSize = normal - <screen> - @android:screenDensity = hdpi - @android:screenSize = normal - <screen> - @android:screenDensity = xhdpi - @android:screenSize = normal diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/56_support_gltext_warning.xml b/manifmerger/src/test/java/com/android/manifmerger/data/56_support_gltext_warning.xml deleted file mode 100755 index 114e9f4..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/56_support_gltext_warning.xml +++ /dev/null @@ -1,151 +0,0 @@ -# -# Test supports-gl-texture: -# - it's a warning if the library defines a supports-gl-texture not in the application. -# - this does not actually merge anything. The XML is not changed at all. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- this is the same supports-gl-texture than in the main. --> - <supports-gl-texture android:name="some.gl.texture1" /> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <!-- this is the not same supports-gl-texture than in the main. --> - <supports-gl-texture android:name="some.gl.texture3" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-configuration - android:reqFiveWayNav="true" - android:reqHardKeyboard="false" - android:reqKeyboardType="undefined" - android:reqNavigation="nonav" - android:reqTouchScreen="stylus" - /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <supports-gl-texture android:name="some.gl.texture1" /> - <supports-gl-texture android:name="some.gl.texture2" /> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - </application> - -</manifest> - - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-gl-texture defined in library, missing from main manifest: -<supports-gl-texture> - @android:name = some.gl.texture3 diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/60_merge_order.xml b/manifmerger/src/test/java/com/android/manifmerger/data/60_merge_order.xml deleted file mode 100755 index d6767f7..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/60_merge_order.xml +++ /dev/null @@ -1,318 +0,0 @@ -# -# Test merge order: -# - When activity / activity-alias / service / receiver / provider are merged, -# we do a comparison to check whether the elements are already present in the -# main manifest. The order of the elements must NOT matter in the comparison, -# nor does the whitespace between them. -# - What this checks is that the order of the elements or attributes within -# the elements should not matter. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.Activity1" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <meta-data - android:name="metaName" - android:value="metaValue" - android:resource="@color/someColor" /> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="android.intent.action.BOOT_COMPLETED" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THIS" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THAT" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.TIMEZONE_CHANGED" /> - <action android:name="android.intent.action.TIME_SET" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.PHONE_STATE"/> - </intent-filter> - </receiver> - - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - - <!-- When comparing duplicate elements, whitespace and comments are ignored. --> - - <intent-filter> - <action android:name="com.example.IN_APP_NOTIFY" /> - <action android:name="com.example.RESPONSE_CODE" /> - <action android:name="com.example.PURCHASE_STATE_CHANGED" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <meta-data - android:name="metaName2" - android:value="metaValue2" - android:resource="@color/someColor2" - /> - </activity> - </application> -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- Redefine the same elements as in the main manifest except it changes - the attribute order and the the inner elements order. --> - <application - android:name="com.example.TheApp" - android:icon="@drawable/app_icon" - android:label="@string/app_name" - android:allowBackup="true" - android:killAfterRestore="true" - android:restoreAnyVersion="true" - android:backupAgent="com.example.app.BackupAgentClass" - > - - <!-- Receiver --> - <receiver - android:icon="@drawable/app_icon" - android:name="com.example.AppReceiver" - > - <intent-filter> - <action android:name="android.intent.action.TIME_SET" /> - <action android:name="android.intent.action.TIMEZONE_CHANGED" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THIS" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.PHONE_STATE"/> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.BOOT_COMPLETED" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THAT" /> - </intent-filter> - </receiver> - - <activity - android:theme="@style/Lib.Theme" - android:name="com.example.LibActivity" - android:icon="@drawable/lib_activity_icon" - android:label="@string/lib_activity_name" - > - <!-- When comparing duplicate elements, whitespace and comments are ignored. --> - <intent-filter> - <category android:name="android.intent.category.LAUNCHER" /> - <action android:name="android.intent.action.MAIN" /> - </intent-filter> - <meta-data - android:resource="@color/someColor2" - android:value="metaValue2" - android:name="metaName2"> - </meta-data> - <intent-filter> - <action android:name="com.example.IN_APP_NOTIFY" /> - <action android:name="com.example.PURCHASE_STATE_CHANGED" /> - <action android:name="com.example.RESPONSE_CODE" /> - </intent-filter> - </activity> - - <activity - android:icon="@drawable/activity_icon" - android:label="@string/activity_name" - android:name="com.example.Activity1" - android:theme="@style/Some.Theme"> - <meta-data - android:value="metaValue" - android:name="metaName" - android:resource="@color/someColor" /> - <intent-filter> - <category android:name="android.intent.category.LAUNCHER" /> - <action android:name="android.intent.action.MAIN" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <!-- The whitespace and alignment is also drastically different here and has - no impact whatsoever on the content's comparison. - Some empty elements have been 'uncollapsed' with their closing element separated. --> - <activity android:label="@string/activity_name" android:icon="@drawable/activity_icon" android:theme="@style/Some.Theme" android:name="com.example.Activity1"> - <intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter> - <intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter> - <meta-data android:value="metaValue" android:resource="@color/someColor" android:name="metaName" /> - </activity> - <activity android:label="@string/lib_activity_name" android:icon="@drawable/lib_activity_icon" android:name="com.example.LibActivity" android:theme="@style/Lib.Theme"><intent-filter> - <action android:name="com.example.IN_APP_NOTIFY" /> <action android:name="com.example.RESPONSE_CODE" /> <action android:name="com.example.PURCHASE_STATE_CHANGED" /> - </intent-filter> - <intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <meta-data android:name="metaName2" android:value="metaValue2" android:resource="@color/someColor2" - /> - </activity> - - <!-- Receiver --> - <receiver android:icon="@drawable/app_icon" android:name="com.example.AppReceiver" > - <intent-filter><action android:name="android.intent.action.TIME_SET"></action> - <action android:name="android.intent.action.TIMEZONE_CHANGED" /></intent-filter> - <intent-filter><action android:name="android.intent.action.PHONE_STATE" > - </action></intent-filter> - <intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /> - </intent-filter> - <intent-filter><action android:name="com.example.intent.action.DO_THIS" /></intent-filter> - <intent-filter><action android:name="com.example.intent.action.DO_THAT" /></intent-filter> - </receiver> - </application> -</manifest> - - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1"> - - <application - android:label="@string/app_name" - android:icon="@drawable/app_icon" - android:backupAgent="com.example.app.BackupAgentClass" - android:restoreAnyVersion="true" - android:allowBackup="true" - android:killAfterRestore="true" - android:name="com.example.TheApp" > - - <activity - android:name="com.example.Activity1" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <meta-data - android:name="metaName" - android:value="metaValue" - android:resource="@color/someColor" /> - </activity> - - <!-- Receiver --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="android.intent.action.BOOT_COMPLETED" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THIS" /> - </intent-filter> - <intent-filter> - <action android:name="com.example.intent.action.DO_THAT" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.TIMEZONE_CHANGED" /> - <action android:name="android.intent.action.TIME_SET" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.PHONE_STATE"/> - </intent-filter> - </receiver> - - <activity - android:name="com.example.LibActivity" - android:label="@string/lib_activity_name" - android:icon="@drawable/lib_activity_icon" - android:theme="@style/Lib.Theme"> - - <!-- When comparing duplicate elements, whitespace and comments are ignored. --> - - <intent-filter> - <action android:name="com.example.IN_APP_NOTIFY" /> - <action android:name="com.example.RESPONSE_CODE" /> - <action android:name="com.example.PURCHASE_STATE_CHANGED" /> - </intent-filter> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - <meta-data - android:name="metaName2" - android:value="metaValue2" - android:resource="@color/someColor2" - /> - </activity> - </application> -</manifest> - -@errors - -P [ManifestMergerTest0_main.xml:37, ManifestMergerTest1_lib1.xml:26] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element. -P [ManifestMergerTest0_main.xml:5, ManifestMergerTest1_lib1.xml:41] Skipping identical /manifest/application/activity[@name=com.example.Activity1] element. -P [ManifestMergerTest0_main.xml:18, ManifestMergerTest1_lib1.xml:7] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver] element. -P [ManifestMergerTest0_main.xml:5, ManifestMergerTest2_lib2.xml:6] Skipping identical /manifest/application/activity[@name=com.example.Activity1] element. -P [ManifestMergerTest0_main.xml:37, ManifestMergerTest2_lib2.xml:11] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element. -P [ManifestMergerTest0_main.xml:18, ManifestMergerTest2_lib2.xml:20] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver] element. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/65_override_app.xml b/manifmerger/src/test/java/com/android/manifmerger/data/65_override_app.xml deleted file mode 100755 index 464b52f..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/65_override_app.xml +++ /dev/null @@ -1,197 +0,0 @@ -# -# Test the tools:merge="override" tag on an application. -# It essentially ignores _any_ application tag from libraries. -# All other non-application elements are merged as usual. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - - <application - tools:merge="override" - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - </application> - -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> - <application android:name="TheApp" > - <activity android:name=".WidgetLibrary1" /> - </application> - -</manifest> - - -@lib2_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib2"> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> - <application - android:name="com.example.app1.TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".WidgetLibrary2" /> - <activity android:name=".LibActivity" /> - </application> - -</manifest> - - -@lib3_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib3"> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> - <application android:name="com.example.app1.TheApp"> - <activity android:name=".WidgetLibrary3" /> - </application> - -</manifest> - - -@lib4_not_package - -<!-- It's an error for the manifest to lack a 'package' attribute. - We just emit a warning in this case. ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android"> - - <!-- Permission tree for lib4 --> - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> - <application> - <!-- These class name can't be expanded due to the lack of 'package' attribute. --> - <activity android:name=".LibActivity4" /> - <service android:name=".LibService4" /> - <receiver android:name=".LibReceiver4" /> - <provider android:name=".LibProvider4" /> - - </application> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <supports-screens - android:largeScreens="true" - android:smallScreens="true" - android:normalScreens="true" - android:resizeable="true" - android:xlargeScreens="true" - /> - - <uses-permission android:name="android.permission.INTERNET" /> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - </application> - - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - - <permission - android:description="Insert boring description here" - android:icon="@drawable/robot" - android:label="Danger, Will Robinson!" - android:name="com.example.DangerWillRobinson" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="dangerous" /> - - <uses-feature - android:name="android.hardware.touchscreen" - android:required="false" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <!-- Permission tree for lib4 --> - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - -</manifest> - -@errors - -W [ManifestMergerTest4_lib4_not_package.xml:1] Missing 'package' attribute in manifest. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/66_remove_app.xml b/manifmerger/src/test/java/com/android/manifmerger/data/66_remove_app.xml deleted file mode 100755 index a1b04b5..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/66_remove_app.xml +++ /dev/null @@ -1,53 +0,0 @@ -# -# Test how elements are removed by tools:merge="remove". -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- The "remove" tag will eradicate this element from the output. --> - <application - tools:merge="remove" - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - </application> -</manifest> - - -@lib1_widget - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.lib1"> - - <!-- This application and all its activities or content is ignored because the - main manifest requested to remove the application element. --> - <application android:name="TheApp" > - <activity android:name=".WidgetLibrary1" /> - </application> -</manifest> - - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- The "remove" tag will eradicate this element from the output. --> -</manifest> - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/67_override_activities.xml b/manifmerger/src/test/java/com/android/manifmerger/data/67_override_activities.xml deleted file mode 100755 index 8bcdb63..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/67_override_activities.xml +++ /dev/null @@ -1,159 +0,0 @@ -# -# Test how elements are overriden by tools:merge="override". -# The override only blocks elements that would be merged. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" tools:merge="override" /> - <receiver android:name="AppReceiver" tools:merge="override"/> - <activity android:name="com.example.lib2.LibActivity" /> - <service android:name="com.example.AppService1" tools:merge="override" /> - <provider android:name="com.example.Provider1" tools:merge="override" /> - <activity-alias android:name="AliasActivity1" tools:merge="override" /> - - </application> -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example"> - - <application> - <!-- Activity merged --> - <activity android:name=".WidgetLibrary1" /> - - <!-- Conflicting activity ignored by override --> - <activity - android:name="com.example.MainActivity" - android:label="@string/activity_name" - android:icon="@drawable/activity_icon" - android:theme="@style/Some.Theme"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <!-- Conflicting receiver ignored by override --> - <receiver - android:name="com.example.AppReceiver" - android:icon="@drawable/app_icon"> - <intent-filter> - <action android:name="com.example.action.ACTION_CUSTOM" /> - </intent-filter> - </receiver> - - <!-- Receiver merged --> - <receiver android:name="LibReceiver" /> - - <!-- Conflicting alias activity ignored by override --> - <activity-alias - android:name="com.example.AliasActivity1" - android:targetActivity="com.example.MainActivity1" - android:label="@string/alias_name1" - android:icon="@drawable/alias_icon1"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- Alias activity merged --> - <activity-alias - android:name="com.example.alias.MyActivity2" - android:targetActivity="com.example.MainActivity2" - android:label="@string/alias_name2" - android:icon="@drawable/alias_icon2"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- Conflicting service ignored by override --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService1" /> - - <!-- Service merged --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService2" /> - - <!-- Conflicting provider ignored by override --> - <provider - android:name="com.example.Provider1" - android:authorities="com.example.android.apis.app.thingy1" - android:enabled="@bool/someConditionalValue" /> - - <!-- Provider merged --> - <provider - android:name="com.example.Provider2" /> - - </application> -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <application - android:name="com.example.TheApp" - android:backupAgent="com.example.MyBackupAgent" > - <activity android:name="com.example.MainActivity" /> - <receiver android:name="com.example.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - <service android:name="com.example.AppService1" /> - <provider android:name="com.example.Provider1" /> - <activity-alias android:name="com.example.AliasActivity1" /> - <!-- Activity merged --> - <activity android:name="com.example.WidgetLibrary1" /> - - <!-- Alias activity merged --> - <activity-alias - android:name="com.example.alias.MyActivity2" - android:targetActivity="com.example.MainActivity2" - android:label="@string/alias_name2" - android:icon="@drawable/alias_icon2"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <!-- Service merged --> - <service - android:icon="@drawable/app_icon" - android:name="com.example.AppService2" /> - - <!-- Receiver merged --> - <receiver android:name="com.example.LibReceiver" /> - - <!-- Provider merged --> - <provider - android:name="com.example.Provider2" /> - - </application> -</manifest> - -@errors - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/68_override_uses.xml b/manifmerger/src/test/java/com/android/manifmerger/data/68_override_uses.xml deleted file mode 100755 index c33f489..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/68_override_uses.xml +++ /dev/null @@ -1,206 +0,0 @@ -# -# Test how elements are overriden by tools:merge="override". -# The removal prevents the actual merge operation. -# However items are still checked out for consistency (just not merged anymore) -# and thus still produce warnings. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - <uses-sdk android:targetSdkVersion="14" tools:merge="override" /> - - <!-- Ignore permissions elements from lib that would conflict because - their definition is different. --> - <permission - tools:merge="override" - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - tools:merge="override" - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - tools:merge="override" - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <!-- uses-feature is never merged, only checked, so tools:merge=override does nothing. --> - <uses-feature - android:name="com.example.SomeFeature0" - android:glEsVersion="0x00020001" /> - <!-- Ignore uses-feature from library, which would change required to - true if it were merged. --> - <uses-feature - tools:merge="override" - android:name="com.example.SomeFeature1" - android:required="false" /> - - <!-- supports-screens is never merged, only checked, so tools:merge=override does nothing. --> - <supports-screens - tools:merge="override" - android:smallScreens="true" - android:resizeable="false" - /> - - <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=override does nothing. --> - <supports-gl-texture android:name="some.gl.texture1" tools:merge="override" /> - - <application android:name="com.example.TheApp" > - <!-- Ignore uses-library from library, which would change required to - true if it were merged. --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" - tools:merge="override" /> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example"> - - <!-- The app can cope with API 1 but this library can only cope with API 4. --> - <uses-sdk android:minSdkVersion="4" /> - - <!-- Ignored permissions --> - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.AnotherGroup" - android:protectionLevel="system" /> - - <permission-group - android:label="Nobody expects the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:description="This is not the same label" - android:name="com.example.PermTree" /> - - <!-- GL 0.0 is a warning which is not prevented by tools:merge=override. --> - <uses-feature - android:name="com.example.SomeFeature0" - android:glEsVersion="0x00000000" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="true" /> - - <!-- supports-screens isn't really merged, just checked, so tools:merge=override does nothing. --> - <!-- this is the not same supports-screens than in the main, will till make a warning. --> - <supports-screens - android:smallScreens="false" - android:resizeable="false" - /> - - <!-- supports-gl-texture isn't really merged, just checked, so tools:merge=override does nothing. --> - <!-- this is the not same supports-gl-texture than in the main. --> - <supports-gl-texture android:name="some.gl.texture3" /> - - <application android:name="com.example.TheApp" > - <!-- Ignored uses-library --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="true" /> - - </application> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example"> - - <!-- The app targets API 14 but this library targets 42. --> - <uses-sdk android:targetSdkVersion="42" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - <uses-sdk android:targetSdkVersion="14" /> - - <!-- Ignore permissions elements from lib that would conflict because - their definition is different. --> - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <!-- uses-feature is never merged, only checked, so tools:merge=override does nothing. --> - <uses-feature - android:name="com.example.SomeFeature0" - android:glEsVersion="0x00020001" /> - <!-- Ignore uses-feature from library, which would change required to - true if it were merged. --> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="false" /> - - <!-- supports-screens is never merged, only checked, so tools:merge=override does nothing. --> - <supports-screens - android:smallScreens="true" - android:resizeable="false" - /> - - <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=override does nothing. --> - <supports-gl-texture android:name="some.gl.texture1" /> - - <application android:name="com.example.TheApp" > - <!-- Ignore uses-library from library, which would change required to - true if it were merged. --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - </application> - -</manifest> - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:19] /manifest/supports-screens defined in library, missing from main manifest: -<supports-screens> - @android:resizeable = false - @android:smallScreens = false -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:23] /manifest/supports-gl-texture defined in library, missing from main manifest: -<supports-gl-texture> - @android:name = some.gl.texture3 -W [ManifestMergerTest1_lib1.xml:14] Ignoring <uses-feature android:glEsVersion='0x00000000'> because it's smaller than 1.0. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/69_remove_uses.xml b/manifmerger/src/test/java/com/android/manifmerger/data/69_remove_uses.xml deleted file mode 100755 index 03ba65c..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/69_remove_uses.xml +++ /dev/null @@ -1,178 +0,0 @@ -# -# Test how elements are removed by tools:merge="remove". -# The removal prevents the actual merge operation. -# However items are still checked out for consistency (just not merged anymore) -# and thus still produce warnings. -# - -@main - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - <uses-sdk android:targetSdkVersion="14" tools:merge="remove" /> - - <!-- Ignore permissions elements from lib that would conflict because - their definition is different. --> - <permission - tools:merge="remove" - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.MasterControlPermission" - android:protectionLevel="signatureOrSystem" /> - - <permission-group - tools:merge="remove" - android:description="Nobody expects..." - android:icon="@drawable/ignored_icon" - android:label="the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - tools:merge="remove" - android:label="This is not a label" - android:name="com.example.PermTree" /> - - <!-- uses-feature is never merged, only checked, so tools:merge=remove does nothing. --> - <uses-feature - tools:merge="remove" - android:name="com.example.SomeFeature0" - android:glEsVersion="0x00020001" /> - <!-- Ignore uses-feature from library, which would change required to - true if it were merged. --> - <uses-feature - tools:merge="remove" - android:name="com.example.SomeFeature1" - android:required="false" /> - - <!-- supports-screens is never merged, only checked, so tools:merge=remove does nothing. --> - <supports-screens - tools:merge="remove" - android:smallScreens="true" - android:resizeable="false" - /> - - <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=remove does nothing. --> - <supports-gl-texture android:name="some.gl.texture1" tools:merge="remove" /> - - <application android:name="com.example.TheApp" > - <!-- Ignore uses-library from library, which would change required to - true if it were merged. --> - <uses-library - tools:merge="remove" - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="false" /> - - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example"> - - <!-- The app can cope with API 1 but this library can only cope with API 4. --> - <uses-sdk android:minSdkVersion="4" /> - - <!-- Ignored permissions --> - <permission - android:name="com.example.WhatWereYouThinking" - android:permissionGroup="com.example.AnotherGroup" - android:protectionLevel="system" /> - - <permission-group - android:label="Nobody expects the Spanish Inquisition" - android:name="com.example.MasterControlPermission" /> - - <permission-tree - android:description="This is not the same label" - android:name="com.example.PermTree" /> - - <!-- GL 0.0 is a warning which is not prevented by tools:merge=remove. --> - <uses-feature - android:name="com.example.SomeFeature0" - android:glEsVersion="0x00000000" /> - <uses-feature - android:name="com.example.SomeFeature1" - android:required="true" /> - - <!-- supports-screens isn't really merged, just checked, so tools:merge=remove does nothing. --> - <!-- this is the not same supports-screens than in the main, will till make a warning. --> - <supports-screens - android:smallScreens="false" - android:resizeable="false" - /> - - <!-- supports-gl-texture isn't really merged, just checked, so tools:merge=remove does nothing. --> - <!-- this is the not same supports-gl-texture than in the main. --> - <supports-gl-texture android:name="some.gl.texture3" /> - - <application android:name="com.example.TheApp" > - <!-- Ignored uses-library --> - <uses-library - android:name="com.example.SomeLibrary4_RequiredFalse" - android:required="true" /> - - </application> - -</manifest> - - -@lib2 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example"> - - <!-- The app targets API 14 but this library targets 42. --> - <uses-sdk android:targetSdkVersion="42" /> - -</manifest> - - -@result - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example" - android:versionCode="100" - android:versionName="1.0.0"> - - <!-- This is the same as writing android:minSdkVersion="1" --> - - <!-- Ignore permissions elements from lib that would conflict because - their definition is different. --> - - <!-- uses-feature is never merged, only checked, so tools:merge=remove does nothing. --> - <!-- Ignore uses-feature from library, which would change required to - true if it were merged. --> - - <!-- supports-screens is never merged, only checked, so tools:merge=remove does nothing. --> - - <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=remove does nothing. --> - - <application android:name="com.example.TheApp" > - <!-- Ignore uses-library from library, which would change required to - true if it were merged. --> - - </application> - -</manifest> - -@errors - -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:19] /manifest/supports-screens defined in library, missing from main manifest: -<supports-screens> - @android:resizeable = false - @android:smallScreens = false -W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:23] /manifest/supports-gl-texture defined in library, missing from main manifest: -<supports-gl-texture> - @android:name = some.gl.texture3 -W [ManifestMergerTest1_lib1.xml:14] Ignoring <uses-feature android:glEsVersion='0x00000000'> because it's smaller than 1.0. diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/70_expand_fqcns.xml b/manifmerger/src/test/java/com/android/manifmerger/data/70_expand_fqcns.xml deleted file mode 100755 index 9a51a8a..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/70_expand_fqcns.xml +++ /dev/null @@ -1,93 +0,0 @@ -# -# Tests the option to extract prefixes. -# The default is for the manifest merger to expand all the class names -# it finds from their short form (e.g. when the package name is implied) -# to their FQCN. -# - -@main - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" - android:versionCode="1" - android:versionName="1.0" > - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="16" /> - - <application - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" - android:theme="@style/AppTheme" > - <!-- The activity name will be expanded to its full FQCN by default. --> - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> - -</manifest> - - -@lib1 - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" > - - <application> - <!-- The activity name will be expanded to its full FQCN by default. --> - <activity - android:name=".FooActivity" - android:label="@string/title_activity_foo" > - </activity> - </application> - -</manifest> - - -@result - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" - android:versionCode="1" - android:versionName="1.0" > - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="16" /> - - <application - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" - android:theme="@style/AppTheme" > - <!-- The activity name will be expanded to its full FQCN by default. --> - <activity - android:name="com.example.blankactivity5.MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - <!-- The activity name will be expanded to its full FQCN by default. --> - <activity - android:name="com.example.blankactivity5.FooActivity" - android:label="@string/title_activity_foo" > - </activity> - </application> - -</manifest> - -@errors - - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/71_extract_package_prefix.xml b/manifmerger/src/test/java/com/android/manifmerger/data/71_extract_package_prefix.xml deleted file mode 100755 index cf2757e..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/71_extract_package_prefix.xml +++ /dev/null @@ -1,99 +0,0 @@ -# -# Tests the option to extract prefixes. -# The default is for the manifest merger to expand all the class names -# it finds from their short form (e.g. when the package name is implied) -# to their FQCN. Setting ManifMerger.setExtractPackagePrefix(true) prevents -# this expansion and keeps the short class names in the merged result. -# - -@features -setExtractPackagePrefix=true - -@main - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" - android:versionCode="1" - android:versionName="1.0" > - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="16" /> - - <application - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" - android:theme="@style/AppTheme" > - <!-- The activity name will NOT be expanded to its full FQCN because - ManifMerger.setExtractPackagePrefix is set to true. --> - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> - -</manifest> - - -@lib1 - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" > - - <application> - <!-- The activity name will NOT be expanded to its full FQCN. --> - <activity - android:name=".FooActivity" - android:label="@string/title_activity_foo" > - </activity> - </application> - -</manifest> - - -@result - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.blankactivity5" - android:versionCode="1" - android:versionName="1.0" > - - <uses-sdk - android:minSdkVersion="11" - android:targetSdkVersion="16" /> - - <application - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" - android:theme="@style/AppTheme" > - <!-- The activity name will NOT be expanded to its full FQCN because - ManifMerger.setExtractPackagePrefix is set to true. --> - <activity - android:name=".MainActivity" - android:label="@string/app_name" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - <!-- The activity name will NOT be expanded to its full FQCN. --> - <activity - android:name=".FooActivity" - android:label="@string/title_activity_foo" > - </activity> - </application> - -</manifest> - -@errors - - diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/75_app_metadata_merge.xml b/manifmerger/src/test/java/com/android/manifmerger/data/75_app_metadata_merge.xml deleted file mode 100755 index f8ebf49..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/75_app_metadata_merge.xml +++ /dev/null @@ -1,100 +0,0 @@ -# -# Tests merging application/meta-data. -# Several APIs provide app-specific keys (e.g. Android Backup API, Google Maps API.) -# and the key needs to be placed in the <application> element as meta-data. -# -# This tests the default behavior which is to merge the elements from the library which are new. -# - -@main - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- Merged elements will be appended here at the end. --> - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1"> - - <application android:name="TheApp" > - <activity android:name=".Library1" /> - - <!-- The library maps API key gets merged in the main application. --> - <meta-data - android:name="name.for.maps.api.key" - android:value="your_maps_api_key"/> - - <!-- The library backup key gets merged in the main application. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="your_backup_api_key" /> - </application> - -</manifest> - - -@result - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- Merged elements will be appended here at the end. --> - <activity android:name="com.example.app1.Library1" /> - - <!-- The library maps API key gets merged in the main application. --> - <meta-data - android:name="name.for.maps.api.key" - android:value="your_maps_api_key"/> - - <!-- The library backup key gets merged in the main application. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="your_backup_api_key" /> - </application> - -</manifest> - - -@errors diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/76_app_metadata_ignore.xml b/manifmerger/src/test/java/com/android/manifmerger/data/76_app_metadata_ignore.xml deleted file mode 100755 index c0ad444..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/76_app_metadata_ignore.xml +++ /dev/null @@ -1,103 +0,0 @@ -# -# Tests merging application/meta-data. -# Several APIs provide app-specific keys (e.g. Android Backup API, Google Maps API.) -# and the key needs to be placed in the <application> element as meta-data. -# -# This tests that an application can selectively prevent specific meta-data from -# being merged by using the tools:merge="remove" attribute. -# - -@main - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- We do not want any maps API key to be merged here. --> - <meta-data - android:name="name.for.maps.api.key" - tools:merge="remove" /> - - <!-- Merged elements will be appended here at the end. --> - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1"> - - <application android:name="TheApp" > - <activity android:name=".Library1" /> - - <!-- The library maps API key gets merged in the main application. --> - <meta-data - android:name="name.for.maps.api.key" - android:value="your_maps_api_key"/> - - <!-- The library backup key gets merged in the main application. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="your_backup_api_key" /> - </application> - -</manifest> - - -@result - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- We do not want any maps API key to be merged here. --> - - <!-- Merged elements will be appended here at the end. --> - <activity android:name="com.example.app1.Library1" /> - - <!-- The library backup key gets merged in the main application. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="your_backup_api_key" /> - </application> - -</manifest> - - -@errors diff --git a/manifmerger/src/test/java/com/android/manifmerger/data/77_app_metadata_conflict.xml b/manifmerger/src/test/java/com/android/manifmerger/data/77_app_metadata_conflict.xml deleted file mode 100755 index 9c96b44..0000000 --- a/manifmerger/src/test/java/com/android/manifmerger/data/77_app_metadata_conflict.xml +++ /dev/null @@ -1,131 +0,0 @@ -# -# Tests merging application/meta-data. -# Several APIs provide app-specific keys (e.g. Android Backup API, Google Maps API.) -# and the key needs to be placed in the <application> element as meta-data. -# -# This tests the default behavior which is to conflict when a library tries to -# add a meta-data which is has the same name but not the same value as one already -# defined in the application. -# -# The application can also override a meta-data using the tools:merge="override" attribute. -# This lets the main application define a meta-data and prevent any library ones from being -# merged and potentially conflict. -# - -@fails - -@main - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="TheApp" - android:backupAgent=".MyBackupAgent" > - <activity android:name=".MainActivity" /> - <receiver android:name="AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- The library has a maps API key that would conflict but it will - actually be ignored since the merge-override flag is set. --> - <meta-data - tools:merge="override" - android:name="name.for.maps.api.key" - android:value="the_apps_maps_api_key"/> - - <!-- The library has a backup API key will conflict since it has a - different value and the merge operation isn't overridden. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="the_apps_backup_api_key" /> - - <!-- Merged elements will be appended here at the end. --> - </application> - -</manifest> - - -@lib1 - -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1"> - - <application android:name="TheApp" > - <activity android:name=".Library1" /> - - <!-- The library maps API key doesn't get merged in the main application. --> - <meta-data - android:name="name.for.maps.api.key" - android:value="the_library1_maps_api_key"/> - - <!-- The library backup key doesn't get merged in the main application. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="the_library1_backup_api_key" /> - </application> - -</manifest> - - -@result - -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.app1" - android:versionCode="100" - android:versionName="1.0.0"> - - <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> - - <application - android:name="com.example.app1.TheApp" - android:backupAgent="com.example.app1.MyBackupAgent" > - <activity android:name="com.example.app1.MainActivity" /> - <receiver android:name="com.example.app1.AppReceiver" /> - <activity android:name="com.example.lib2.LibActivity" /> - - <!-- This key is defined in the main application. --> - <meta-data - android:name="name.for.yet.another.api.key" - android:value="your_yet_another_api_key"/> - - <!-- The library has a maps API key that would conflict but it will - actually be ignored since the merge-override flag is set. --> - <meta-data - android:name="name.for.maps.api.key" - android:value="the_apps_maps_api_key"/> - - <!-- The library has a backup API key will conflict since it has a - different value and the merge operation isn't overridden. --> - <meta-data - android:name="name.for.backup.api.key" - android:value="the_apps_backup_api_key" /> - - <!-- Merged elements will be appended here at the end. --> - <activity android:name="com.example.app1.Library1" /> - </application> - -</manifest> - - -@errors - -E [ManifestMergerTest0_main.xml:17, ManifestMergerTest1_lib1.xml:10] Trying to merge incompatible /manifest/application/meta-data[@name=name.for.backup.api.key] element: - <meta-data - @android:name="name.for.backup.api.key" --- @android:value="the_apps_backup_api_key"> - <meta-data - @android:name="name.for.backup.api.key" -++ @android:value="the_library1_backup_api_key"> |