1/** 2 * @fileoverview Class OTAInput is used to configure and create a process in 3 * the backend to to start OTA package generation. 4 * @package vue-uuid 5 * @package ApiServices 6 */ 7import { uuid } from 'vue-uuid' 8import ApiServices from './ApiService.js' 9 10export class OTAConfiguration { 11 /** 12 * Initialize the input for the api /run/<id> 13 */ 14 constructor() { 15 /** 16 * Please refer to: 17 * https://source.corp.google.com/android/build/make/tools/releasetools/ota_from_target_files.py 18 * for the complete and up-to-date configurations that can be set for 19 * the OTA package generation. 20 * TODO (lishutong): there are dependencies on this flags, 21 * disable checkboxes of which dependencies are not fulfilled. 22 */ 23 this.verbose = false, 24 this.isIncremental = false, 25 this.partial = [], 26 this.isPartial = false, 27 this.extra_keys = [], 28 this.extra = '' 29 } 30 31 /** 32 * Take in multiple paths of target and incremental builds and generate 33 * OTA packages between them. If there are n incremental sources and m target 34 * builds, there will be n x m OTA packages in total. If there is 0 35 * incremental package, full OTA will be generated. 36 * @param {Array<String>} targetBuilds 37 * @param {Array<String>} incrementalSources 38 * @return Array<String> 39 */ 40 async sendForms(targetBuilds, incrementalSources = []) { 41 const responses = [] 42 if (!this.isIncremental) { 43 responses.push( 44 ... await Promise.all( 45 targetBuilds.map(async (target) => await this.sendForm(target)) 46 ) 47 ) 48 } else { 49 for (const incremental of incrementalSources) { 50 responses.push( 51 ... await Promise.all( 52 targetBuilds.map( 53 async (target) => await this.sendForm(target, incremental) 54 ) 55 ) 56 ) 57 } 58 } 59 return responses 60 } 61 62 /** 63 * Take in an ordered list of target builds and generate OTA packages between 64 * them in order. For example, if there are n target builds, there will be 65 * n-1 OTA packages. 66 * @param {Array<String>} targetBuilds 67 * @return Array<String> 68 */ 69 async sendChainForms(targetBuilds) { 70 const responses = [] 71 this.isIncremental = true 72 for (let i = 0; i < targetBuilds.length - 1; i++) { 73 let response = 74 await this.sendForm(targetBuilds[i + 1], targetBuilds[i]) 75 responses.push(response) 76 } 77 return responses 78 } 79 80 /** 81 * Start an OTA package generation from target build to incremental source. 82 * Throw an error if not succeed, otherwise will return the message from 83 * the backend. 84 * @param {String} targetBuild 85 * @param {String} incrementalSource 86 * @return String 87 */ 88 async sendForm(targetBuild, incrementalSource = '') { 89 let jsonOptions = Object.assign({}, this) 90 jsonOptions.target = targetBuild 91 jsonOptions.incremental = incrementalSource 92 jsonOptions.isIncremental = !!incrementalSource; 93 jsonOptions.id = uuid.v1() 94 for (let flag of OTAExtraFlags) { 95 if (jsonOptions[flag.key]) { 96 if (jsonOptions.extra_keys.indexOf(flag.key) === -1) { 97 jsonOptions.extra_keys.push(flag.key) 98 } 99 } 100 } 101 let data = await ApiServices.postInput(jsonOptions, jsonOptions.id) 102 return data; 103 } 104 105 /** 106 * Reset all the flags being set in this object. 107 */ 108 reset() { 109 for (let flag of OTAExtraFlags) { 110 if (this[flag.key]) { 111 delete this[flag.key] 112 } 113 } 114 this.constructor() 115 } 116} 117 118export const OTABasicFlags = [ 119 { 120 key: 'isIncremental', 121 label: 'Incremental OTA', 122 requireArg: 'incremental' 123 }, 124 { 125 key: 'isPartial', 126 label: 'Partial OTA', 127 requireArg: 'partial' 128 }, 129 { 130 key: 'verbose', 131 label: 'Verbose' 132 },] 133 134export const OTAExtraFlags = [ 135 { 136 key: 'downgrade', 137 label: 'Downgrade', 138 depend: ['isIncremental'] 139 }, 140 { 141 key: 'override_timestamp', 142 label: 'Override time stamp' 143 }, 144 { 145 key: 'wipe_user_data', 146 label: 'Wipe User data' 147 }, 148 //{ 149 // key: 'retrofit_dynamic_partitions', 150 // label: 'Support dynamic partition' 151 //}, 152 { 153 key: 'skip_compatibility_check', 154 label: 'Skip compatibility check' 155 }, 156 //{ 157 // key: 'output_metadata_path', 158 // label: 'Output metadata path' 159 //}, 160 { 161 key: 'force_non_ab', 162 label: 'Generate non-A/B package' 163 }, 164 /** TODO(lishutong): the following comments are flags 165 * that requires file operation, will add these functions later. 166 */ 167 //{key: 'oem_settings', label: 'Specify the OEM properties', 168 // requireArg: 'oem_settings_files'}, 169 //{key: 'binary', label: 'Use given binary', requireArg: 'binary_file', 170 // depend: ['force_non_ab']}, 171 { 172 key: 'block', 173 label: 'Block-based OTA', 174 depend: ['force_non_ab'] 175 }, 176 //{key: 'extra_script', label: 'Extra script', requireArg: 'script_file', 177 // depend: ['force_non_ab']}, 178 { 179 key: 'full_bootloader', 180 label: 'Full bootloader', 181 depend: ['force_non_ab', 'isIncremental'] 182 }, 183 { 184 key: 'full_radio', 185 label: 'Full radio', 186 depend: ['force_non_ab', 'isIncremental'] 187 }, 188 //{key: 'log_diff', label: 'Log difference', 189 // requireArg: 'log_diff_path',depend: ['force_non_ab', 'isIncremental']}, 190 //{key: 'oem_no_mount', label: 'Do not mount OEM partition', 191 // depend: ['force_non_ab', 'oem_settings']}, 192 //{ 193 // key: 'stash_threshold', 194 // label: 'Threshold for maximum stash size', 195 // requireArg: 'stash_threshold_float', 196 // depend: ['force_non_ab'] 197 //}, 198 //{ 199 // key: 'worker_threads', 200 // label: 'Number of worker threads', 201 // requireArg: 'worker_threads_int', 202 // depend: ['force_non_ab', 'isIncremental'] 203 //}, 204 //{ 205 // key: 'verify', 206 // label: 'Verify the checksum', 207 // depend: ['force_non_ab', 'isIncremental'] 208 //}, 209 { 210 key: 'two_step', 211 label: 'Generate two-step OTA', 212 depend: ['force_non_ab'] 213 }, 214 { 215 key: 'disable_fec_computation', 216 label: 'Disable the on device FEC computation', 217 depend: ['isIncremental'], 218 exclude: ['force_non_ab'] 219 }, 220 { 221 key: 'include_secondary', 222 label: 'Include secondary slot images', 223 exclude: ['force_non_ab', 'isIncremental'] 224 }, 225 //{key: 'payload_signer', label: 'Specify the signer', 226 // requireArg: ['payload_signer_singer'], exclude: ['force_non_ab']}, 227 //{key: 'payload_singer_args', label: 'Specify the args for signer', 228 // requireArg: ['payload_signer_args_args], exclude: ['force_non_ab']}, 229 //{ 230 // key: 'payload_signer_maximum_signature_size', 231 // label: 'The maximum signature size (in bytes)', 232 // requireArg: ['payload_signer_maximum_signature_size_int'], 233 // exclude: ['force_non_ab'] 234 //}, 235 //{key: 'boot_variable_file', label: 'Specify values of ro.boot.*', 236 // requireArg: ['boot_variable_file_file'], exclude: ['force_non_ab']}, 237 { 238 key: 'skip_postinstall', 239 label: 'Skip the postinstall', 240 exclude: ['force_non_ab'] 241 }, 242 //{key: 'custom_image', label: 'Use custom image', 243 // requireArg: ['custom_image_files'], exclude: ['force_non_ab]}, 244 { 245 key: 'disable_vabc', 246 label: 'Disable Virtual A/B compression', 247 exclude: ['force_non_ab'] 248 }, 249 { 250 key: 'vabc_downgrade', 251 label: "Don't disable VABC for downgrading", 252 depend: ['isIncremental', 'downgrade'], 253 exclude: ['force_non_ab'] 254 }, 255] 256 257/** export const requireArgs = new Map([ 258 [ 259 "stash_threshold_float", 260 { 261 type: "BaseInput", 262 label: "Threshold for maximum stash size" 263 } 264 ], 265 [ 266 "worker_threads", 267 { 268 type: "BaseInput", 269 label: "Number of worker threads" 270 } 271 ], 272 [ 273 "payload_signer_maximum_signature_size", 274 { 275 type: "BaseInput", 276 label: "The maximum signature size (in bytes)" 277 } 278 ], 279]) */