OTA升级erase、new、zero流程:

BLOCK升级完整包system.transfer.list中erase、new、zero流程:

走到erase、new、zero说明已经校验OK,进入写BLOCK阶段,具体在BlockImageUpdateFn中实现在updater-script中体现为:block_image_update,方法如下:

Value* BlockImageUpdateFn(const char* name, State* state,const std::vector<std::unique_ptr<Expr>>& argv) {    
	const CommandMap command_map{
        // clang-format off
        { Command::Type::ABORT,             PerformCommandAbort },
        { Command::Type::BSDIFF,            PerformCommandDiff },
        { Command::Type::COMPUTE_HASH_TREE, PerformCommandComputeHashTree },
        { Command::Type::ERASE,             PerformCommandErase },
        { Command::Type::FREE,              PerformCommandFree },
        { Command::Type::IMGDIFF,           PerformCommandDiff },
        { Command::Type::MOVE,              PerformCommandMove },
        { Command::Type::NEW,               PerformCommandNew },
        { Command::Type::STASH,             PerformCommandStash },
        { Command::Type::ZERO,              PerformCommandZero },
    	// clang-format on
    };
    CHECK_EQ(static_cast<size_t>(Command::Type::LAST), command_map.size());
    return PerformBlockImageUpdate(name, state, argv, command_map, false);
}

将命令对应的方法存入CommandMap,继续看PerformBlockImageUpdate方法实现

static Value* PerformBlockImageUpdate(const char* name, State* state,
                                      const std::vector<std::unique_ptr<Expr>>& argv,
                                      const CommandMap& command_map, bool dryrun) {
	...
    std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");//解析system.transfer.list文件到lines
    ...
    if (params.canwrite) {//创建写数据线程
        params.nti.za = za;
        params.nti.entry = new_entry;
        params.nti.brotli_compressed = android::base::EndsWith(new_data_fn->data, ".br");
        if (params.nti.brotli_compressed) {
            // Initialize brotli decoder state.
            params.nti.brotli_decoder_state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
        }
        params.nti.receiver_available = true;
        pthread_mutex_init(&params.nti.mu, nullptr);
        pthread_cond_init(&params.nti.cv, nullptr);
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        //创建线程,receive_brotli_new_data方法内读写数据
        int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti);
        if (error != 0) {
            LOG(ERROR) << "pthread_create failed: " << strerror(error);
            return StringValue("");
        }
    }
    Command::Type cmd_type = Command::ParseType(params.cmdname);//解析命令,
    const CommandFunction& performer = command_map.at(cmd_type);//从命令获取方法
     if (performer(params) == -1) {//调用对应方法,erase 调用PerformCommandErase,new调用PerformCommandNew,erase调用PerformCommandErase
         ...
     }
    
    
}

一、erase 流程:

如:erase 6,134685,163328,164354,228864,229953,257475

static int PerformCommandErase(CommandParameters& params) {
	if (DEBUG_ERASE) {
		return PerformCommandZero(params);
	}
	struct stat sb;
    if (fstat(params.fd, &sb) == -1) {//文件描述符的状态信息
        PLOG(ERROR) << "failed to fstat device to erase";
        return -1;
    }
    if (!S_ISBLK(sb.st_mode)) {
        LOG(ERROR) << "not a block device; skipping erase";
        return -1;
    }
    if (params.cpos >= params.tokens.size()) {
        LOG(ERROR) << "missing target blocks for erase";
        return -1;
    }
    RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
    CHECK(static_cast<bool>(tgt));
    if (params.canwrite) {
         LOG(INFO) << " erasing " << tgt.blocks() << " blocks";
		for (const auto& [begin, end] : tgt) {//如:[134685,163328]
            off64_t offset = static_cast<off64_t>(begin) * BLOCKSIZE;
            size_t size = (end - begin) * BLOCKSIZE;//block大小:(163328-134685)*4096=116,548,367
            if (!discard_blocks(params.fd, offset, size, true /* force */)) {
        		return -1;
      	    }
        }
    }
}

调用discard_blocks丢掉对应的block

static bool discard_blocks(int fd, off64_t offset, uint64_t size, bool force = false) {
    // Don't discard blocks unless the update is a retry run or force == true
    if (!is_retry && !force) {
        return true;
    }
    uint64_t args[2] = { static_cast<uint64_t>(offset), size };
    if (ioctl(fd, BLKDISCARD, &args) == -1) {//	最终调用系统ioctl丢弃指定BLOCK(163328-134685)
        // On devices that does not support BLKDISCARD, ignore the error.
        if (errno == EOPNOTSUPP) {
          return true;
        }
        PLOG(ERROR) << "BLKDISCARD ioctl failed";
        return false;
    }
    return true;
}

二、zero流程

zero调用PerformCommandZero实现

三、new 流程:

new 调用PerformCommandNew方法

static int PerformCommandNew(CommandParameters& params) {
	if (params.cpos >= params.tokens.size()) {
    	LOG(ERROR) << "missing target blocks for new";
    	return -1;
  	}
    RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
  	CHECK(static_cast<bool>(tgt));
    if (params.canwrite) {
        LOG(INFO) << " writing " << tgt.blocks() << " blocks of new data";
        pthread_mutex_lock(&params.nti.mu);
        //创建一个RangeSinkWriter包含block范围(RangeSet),在PerformBlockImageUpdate创建的线程中receive_brotli_new_data检测到params.nti.writer不为空则开始执行写动作,写完后将params.nti.writer置空
        params.nti.writer = std::make_unique<RangeSinkWriter>(params.fd, tgt);
        pthread_cond_broadcast(&params.nti.cv);
        while (params.nti.writer != nullptr) {//判断是否写完数据
             if (!params.nti.receiver_available) {
                 LOG(ERROR) << "missing " << (tgt.blocks() * BLOCKSIZE - params.nti.writer->BytesWritten())
                   << " bytes of new data";
                 pthread_mutex_unlock(&params.nti.mu);
        		return -1;
             } 
            pthread_cond_wait(&params.nti.cv, &params.nti.mu);
        }
         pthread_mutex_unlock(&params.nti.mu);
    }
    params.written += tgt.blocks();
 	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值