19 Apr 2015
Viewgroup.addView()有5个重载方法:
void addView(View child, int index, ViewGroup.LayoutParams params)
void addView(View child, ViewGroup.LayoutParams params)
void addView(View child, int index)
void addView(View child)
void addView(View child, int width, int height)
如果需要想重写addView()实际只需要重写**addView(View child, int index, ViewGroup.LayoutParams params)**
即可。
看一下addView的源码:
public void addView(View child) {
addView(child, -1);
}
public void addView(View child, int index) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
public void addView(View child, int width, int height) {
final LayoutParams params = generateDefaultLayoutParams();
params.width = width;
params.height = height;
addView(child, -1, params);
}
public void addView(View child, LayoutParams params) {
addView(child, -1, params);
}
/**
* Adds a child view with the specified layout parameters.
*
* @param child the child view to add
* @param index the position at which to add the child
* @param params the layout parameters to set on the child
*/
public void addView(View child, int index, LayoutParams params) {
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate();
addViewInner(child, index, params, false);
}
18 Apr 2015
func someFunctionThatTakesAClosure(closure: () -> () ) {
}
Not use trailing closure
someFunctionThatTakesAClosure({
})
Use trailing closure
someFunctionThatTakesAClosure() {
}
Example
let digitNames = [
0: "Zero", 1: "One", 2: "two", 3: "Three", 4: "Foure",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map{
(var number)->String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
println(strings)
ref: The Swift Programming Language
16 Apr 2015
好吧,swift这回要逆天了
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let(x, y) where x == y:
println("(\(x), \(y)) is on the line x == y")
case let(x, y) where x == -y:
println("(\(x), \(y)) is on the line x == -y")
case let(x, y):
println("(\(x), \(y)) is just some arbitary point")
}
ref: The Swift Programming Language
10 Apr 2015
OTA升级脚本build/tools/releasetoolsrecovery-resource.dat
# Recovery is generated as a patch using both the boot image
# (which contains the same linux kernel as recovery) and the file
# /system/etc/recovery-resource.dat (which contains all the images
# used in the recovery UI) as sources. This lets us minimize the
# size of the patch, which must be included in every OTA package.
#
# For older builds where recovery-resource.dat is not present, we
# use only the boot image as the source. ref: build/tools/releasetools/ota_from_target_files
source of imgdiff and bsdiffbootable/recovery/applypatch
Android端的升级脚本两步策略中的第二步,升级重启后执行的脚本(包括建立软链接和权限设置)。
META-INF/com/google/android/updater-script
imgdiff的参数
imgdiff是android提供的用来生成binary patch的工具,android同时还提供了另一个binary patch工具是bsdiff。
usage: -z <src-img> <tgt-img> <patch-file>
-z: 输入文件是否是ZIP格式
-b: 额外的二进制文件,在OTA中,这个文件就是recovery-resource.dat
imgdiff和bsdiff的区别
看下下面这段摘自imgdiff.c的说明就明白了:
- This program(imgdiff) constructs binary patches for images -- such as boot.img
- and recovery.img -- that consist primarily of large chunks of gzipped
- data interspersed with uncompressed data. Doing a naive bsdiff of
- these files is not useful because small changes in the data lead to
- large changes in the compressed bitstream; bsdiff patches of gzipped
- data are typically as large as the data itself
生成全包和差分包生成全包命令
生成全包命令
ota_from_target_files -f 0 -d "MMC" -p out/host/linux-x86/ -k build/target/product/security/testkey -v product-target_files-eng.hostname.zip ~/tmp/full_OTA.zip
生成差分包命令
ota_from_target_files -f 0 -d "MMC" -p out/host/linux-x86 -k build/target/product/security/testkey -v -i product-target_files-eng-old.host.zip product-target_files-eng-new.host.zip ~/tmp/increment_OTA.zip
相关的代码调用
ota_from_target_files中
if OPTIONS.incremental_source is None:
WriteFullOTAPackage(input_zip, output_zip, OPTIONS.fota)
if OPTIONS.package_key is None:
OPTIONS.package_key = OPTIONS.info_dict.get(
"default_system_dev_certificate",
"build/target/product/security/testkey")
else:
print "unzipping source target-files..."
OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)
OPTIONS.target_info_dict = OPTIONS.info_dict
OPTIONS.source_info_dict = common.LoadInfoDict(source_zip, OPTIONS.device_type)
if OPTIONS.package_key is None:
OPTIONS.package_key = OPTIONS.source_info_dict.get(
"default_system_dev_certificate",
"build/target/product/security/testkey")
if OPTIONS.verbose:
print "--- source info ---"
common.DumpInfoDict(OPTIONS.source_info_dict)
WriteIncrementalOTAPackage(input_zip, source_zip, output_zip, OPTIONS.fota)
生成OTA步骤
- unzip
- imgdiff / bsdiff
- zip
- openssl
- signapk
OTA原始包
可用于生成OTA的文件一版在目录out/target/product/somename/obj/PACKAGING/target_files_intermediates
下。
OTA中system下文件的权限设置
ota_from_target_files中:
@classmethod
def GetMetadata(cls, input_zip):
The target_files contains a record of what the uid,
gid, and mode are supposed to be.
output = input_zip.read("META/filesystem_config.txt")
for line in output.split("\n"):
if not line: continue
columns = line.split()
name, uid, gid, mode = columns[:4]
selabel = None
capabilities = None
After the first 4 columns, there are a series of key=value
pairs. Extract out the fields we care about.
for element in columns[4:]:
key, value = element.split("=")
if key == "selabel":
selabel = value
if key == "capabilities":
capabilities = value
i = cls.ITEMS.get(name, None)
if i is not None:
i.uid = int(uid)
i.gid = int(gid)
i.mode = int(mode, 8)
i.selabel = selabel
i.capabilities = capabilities
if i.dir:
i.children.sort(key=lambda i: i.name)
set metadata for the files generated by this script.
i = cls.ITEMS.get("system/recovery-from-boot.p", None)
if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None
i = cls.ITEMS.get("system/etc/install-recovery.sh", None)
if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None
从上面的代码可以看到脚本读取的是META/filesystem_config.txt
中的内容,这个文件是有源码编译的生成的。所以如果你增加了一些apk到image中,然后制作OTA,你需要自己赋予你的apk相应的权限,否则在生成OTA的时候就会出错(找不到 uid, gid, mode …),不要试图随意赋这些值。
filesystem_config.txt
这个文件是在build/core/Makefile中生成的:
$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt
$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt
$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt
$(hide) (cd $(zip_root) && zip -q ../$(notdir [email protected]) META/*filesystem_config.txt)
fs_config
这个工具是生成上一步中的filesystem_config.txt的核心,其源码在build/tools/fs_config
参数说明:
// This program takes a list of files and directories (indicated by a
// trailing slash) on the stdin, and prints to stdout each input
// filename along with its desired uid, gid, and mode (in octal).
// The leading slash should be stripped from the input.
//
// After the first 4 columns, optional key=value pairs are emitted
// for each file. Currently, the following keys are supported:
// * -S: selabel=[selinux_label]
// * -C: capabilities=[hex capabilities value]
//
// Example input:
//
// system/etc/dbus.conf
// data/app/
//
// Output:
//
// system/etc/dbus.conf 1002 1002 440
// data/app 1000 1000 771
//
// or if, for example, -S is used:
//
// system/etc/dbus.conf 1002 1002 440 selabel=u:object_r:system_file:s0
// data/app 1000 1000 771 selabel=u:object_r:apk_data_file:s0
//
// Note that the output will omit the trailing slash from
// directories.