重写 ViewGroup 的 addView 方法

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);
    }

Swift Trailing Closure

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

Swift Switch Where Filter

好吧,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

HTTP Cookie属性列表

版本0

cookie-v0(1)

cookie-v0(1)

cookie-v0(2)

cookie-v0(2)

版本1

cookie-v1(1)

cookie-v1(1)

cookie-v1(2)

cookie-v1(2)

ref: 《HTTP权威指南》

Android OTA 升级中的一些零碎知识

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.