Create AVDs from the images automatically am: ae4b5ec96d am: c54f1cde69 am: cc10de1356 am: c643acf55d

Original change: https://android-review.googlesource.com/c/platform/tools/aadevtools/+/1691592

Change-Id: I1e16313875f4bae414cfe6425516c2d2b243079c
diff --git a/avd/README.md b/avd/README.md
index 132665b..b520a80 100644
--- a/avd/README.md
+++ b/avd/README.md
@@ -9,8 +9,10 @@
     * test_avd_avd_image.sh is the test & also examples of how to use it.
 * batch_add_avd_img.sh adds all AVD images listed in the input CSV file & properly patch to be used for Automotive device profiles.
     * avd_img_list.csv is the default CSV file if non is provided & also as an example.
+* create_avd.sh creates a minimal AVD configuration from an AVD image.
+    * test_create_avd.sh is the test & also examples of how to use it.
 * patch_avd.sh changes an AVD configuration for bigger RAM, heap & data disk. So it can perform properly.
 * patch_all_avds.sh changes all AVD configuration for more RAM & heap. So it can perform properly.
     * test_patch_all_avds.sh is the test & also examples of how to use it.
 * set_avds_force_cold_boot.sh sets Cold Boot or Quick Boot for all AVD configurations.
-    * test_set_avds_force_cold_boot.sh is the test & also examples of how to use it.
+    * test_set_avds_force_cold_boot.sh is the test & also examples of how to use it.
\ No newline at end of file
diff --git a/avd/batch_add_avd_img.sh b/avd/batch_add_avd_img.sh
index aa52755..3efc917 100755
--- a/avd/batch_add_avd_img.sh
+++ b/avd/batch_add_avd_img.sh
@@ -22,28 +22,33 @@
 }
 
 MY_NAME=$0
-SCRIPT_NAME=${MY_NAME##*/}
-SCRIPT_DIR=${MY_NAME%/$SCRIPT_NAME}
+SCRIPT_NAME="${MY_NAME##*/}"
+SCRIPT_DIR="${MY_NAME%/$SCRIPT_NAME}"
 echo Running from $SCRIPT_DIR
 
 INPUT_CSV=$1
-if [[ -z $INPUT_CSV ]]; then
+if [[ -z "${INPUT_CSV}" ]]; then
     INPUT_CSV="$SCRIPT_DIR/resource/avd_img_list.csv"
 fi
 
-echo Process $INPUT_CSV
+echo "Process ${INPUT_CSV}"
 header=0
-avd_count=0
-while IFS=',' read -r name api zip others || [ -n "$name" ]; do
-  if [[ "$name" == "name" ]]; then
+avdCount=0
+while IFS=',' read -r name api zip others || [ -n "${name}" ]; do
+  if [[ "${name}" == "name" ]]; then
     # skip header
-    header="$name,$api,$zip"
+    header="${name},${api},${zip}"
   else
-    CMD="VARIANT=$name API_LEVEL=$api OEM_AVD_ZIP=$zip $SCRIPT_DIR/add_avd_img.sh"
-    echo $CMD
-    eval $CMD
+    addAvdImgCmd="VARIANT=${name} API_LEVEL=${api} OEM_AVD_ZIP=${zip} ${SCRIPT_DIR}/add_avd_img.sh"
+    echo "${addAvdImgCmd}"
+    eval "${addAvdImgCmd}"
+
+    createAvdCmd="AVD_IMG_NAME=${name} API_LEVEL=${api} DEFAULT_DEVICE_XML=${SCRIPT_DIR}/resource/devices.xml ${SCRIPT_DIR}/create_avd.sh"
+    echo "${createAvdCmd}"
+    eval "${createAvdCmd}"
+
     echo
-    ((avd_count+=1))
+    ((avdCount+=1))
   fi
 done < $INPUT_CSV
 
@@ -52,3 +57,5 @@
   echo "ERROR: The header:$header is not as expected in $INPUT_CSV"
   cat $INPUT_CSV
 fi
+
+echo "Processed ${avdCount} AVDs"
\ No newline at end of file
diff --git a/avd/create_avd.sh b/avd/create_avd.sh
new file mode 100755
index 0000000..64e9da5
--- /dev/null
+++ b/avd/create_avd.sh
@@ -0,0 +1,185 @@
+#!/bin/bash
+
+# Copyright (C) 2021 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.
+
+readme() {
+  echo '''
+Create an AVD. e.g.
+  AVD_IMG_NAME="sdk_gcar" \
+  API_LEVEL=30 \
+  DEFAULT_DEVICE_XML="./resource/devices.xml" \
+  ./create_avd.sh
+'''
+}
+
+# Export a variable=default_value if it's empty, e.g.
+# exportVar "VAR" "defaultValue"
+exportVar()
+{
+  var=$1
+  defaultValue=$2
+  if [[ -z "${!var}" ]]; then
+    export "${var}=$defaultValue"
+    echo "${var}=$defaultValue"
+  fi
+}
+
+# Export a variable with the value of an XML element in a file as, e.g.
+# getValue "TAG_ID" "d:id" "./resource/devices.xml"
+getValue() {
+  var=$1
+  elementTag=$2
+  file=$3
+  #e.g.        <d:id>aosp_car_10_landscape</d:id>
+  value=$(sed -n -e "s/.*<${elementTag}>\(.*\)<\/${elementTag}>.*/\1/p" "${file}")
+  export "${var}=${value}"
+  echo "${var}=${value}"
+}
+
+if [[ -z "${AVD_IMG_NAME}" || -z "${API_LEVEL}" ]]; then
+  readme
+  exit
+fi
+
+MY_NAME=$0
+SCRIPT_NAME="${MY_NAME##*/}"
+SCRIPT_DIR="${MY_NAME%/$SCRIPT_NAME}"
+echo "Running from ${SCRIPT_DIR}"
+
+# set up for Linux or macOS
+OS="$(uname -s)"
+echo "Running on $OS"
+if [[ $OS == "Linux" ]]; then
+  export ANDROID_SDK_ROOT="${HOME}/Android/Sdk"
+  SED_I_CMD="sed -i "
+elif [[ $OS == "Darwin" ]]; then
+  export ANDROID_SDK_ROOT="${HOME}/Library/Android/sdk"
+  SED_I_CMD="sed -i ''"
+else
+  echo "ERROR: this does not work on $OS"
+  exit
+fi
+echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT}"
+
+if [[ -z ${AVD_IMG_DIR} ]]; then
+  AVD_IMG_DIR="${ANDROID_SDK_ROOT}/system-images/android-${API_LEVEL}/${AVD_IMG_NAME}"
+fi
+echo "AVD_IMG_DIR=${AVD_IMG_DIR}"
+
+if [[ ! -e "${AVD_IMG_DIR}" ]]; then
+  echo "ERROR: no AVD image found at ${AVD_IMG_DIR}"
+  exit
+fi
+
+ABI=$(ls "${AVD_IMG_DIR}")
+if [[ "${ABI}" != "x86" && "${ABI}" != "x86_64" ]]; then
+  echo "ERROR: AVD image zip file format incorrect as ${AVD_DIR} should contain x86 or x86_64 as: https://source.android.com/devices/automotive/start/avd#pack-an-avd-image-zip-file "
+  exit
+fi
+echo "ABI=${ABI}"
+
+# sdk_gcar_30
+AVD_NAME="${AVD_IMG_NAME}_${API_LEVEL}"
+AVD_INI="${HOME}/.android/avd/${AVD_NAME}.ini"
+AVD_PATH_REL="avd/${AVD_NAME}.avd"
+AVD_PATH="${HOME}/.android/${AVD_PATH_REL}"
+AVD_CONFIG_INI="${AVD_PATH}/config.ini"
+
+if [[ -e "${AVD_PATH}" ]]; then
+  echo "NOTE: ${AVD_PATH} exists. Delete them if to recreate, e.g."
+  echo "rm -r ${AVD_PATH} || rm ${AVD_INI}"
+  exit
+fi
+
+# It should be aligned with avdmanager.
+# May use https://developer.android.com/studio/command-line/avdmanager, but
+# 1. more setup steps required for users & 2. slow on parsing image folders
+# So here just add  the bare minimum set up.
+echo "Create ${AVD_INI}"
+echo "avd.ini.encoding=UTF-8
+path=${AVD_PATH}
+path.rel=${AVD_PATH_REL}
+target=android-${API_LEVEL}" >> "${AVD_INI}"
+
+echo
+mkdir -p "${AVD_PATH}"
+USERDATA_DIR="${AVD_PATH}/userdata.img"
+echo "Create Avd Userdata at ${USERDATA_DIR}"
+cp "${AVD_IMG_DIR}/${ABI}/userdata.img" "${USERDATA_DIR}"
+
+DEVICE_XML="${AVD_IMG_DIR}/${ABI}/devices.xml"
+if [[ ! -e "${DEVICE_XML}" ]]; then
+  echo "NOTE: No ${DEVICE_XML} in the AVD image."
+  if [[ ! -e "${DEFAULT_DEVICE_XML}" ]]; then
+    echo "ERROR: Need to set DEFAULT_DEVICE_XML at least."
+    exit
+  else
+    echo "COPY: ${DEFAULT_DEVICE_XML} ${DEVICE_XML}"
+    cp "${DEFAULT_DEVICE_XML}" "${DEVICE_XML}"
+    echo "NOTE: Please restart Android Studio, so the new devics.xml will be properly loaded."
+  fi
+fi
+echo "DEVICE_XML=${DEVICE_XML}"
+getValue "DEVICE_PROFILE_NAME" "d:id" "${DEVICE_XML}"
+getValue "MANUFACTURER" "d:manufacturer" "${DEVICE_XML}"
+getValue "ORIENTATION" "d:screen-orientation" "${DEVICE_XML}"
+getValue "TAG_ID" "d:tag-id" "${DEVICE_XML}"
+getValue "SKIN" "d:skin" "${DEVICE_XML}"
+
+
+if [[ "${ORIENTATION}" == "land" ]]; then
+  ORIENTATION="landscape"
+fi
+
+echo "Create ${AVD_CONFIG_INI}"
+exportVar "TAG_ID" "android-automotive"
+# MANUFACTURER & DEVICE_PROFILE_NAME need to match those in devices.xml
+exportVar "MANUFACTURER" "Android"
+exportVar "DEVICE_PROFILE_NAME" "aosp_car_10_landscape"
+exportVar "ORIENTATION" "landscape"
+exportVar "NCORE" 4
+exportVar "RAM" "4096"
+exportVar "HEAP" "576"
+exportVar "DATA" "6G"
+
+echo "avd.ini.encoding=UTF-8
+AvdId=${AVD_NAME}
+avd.ini.displayname=${AVD_NAME}
+tag.display=${AVD_NAME}
+tag.id=${TAG_ID}
+image.sysdir.1=system-images/android-${API_LEVEL}/${AVD_IMG_NAME}/${ABI}/
+abi.type=${ABI}
+hw.arc=false
+hw.device.manufacturer=${MANUFACTURER}
+hw.device.name=${DEVICE_PROFILE_NAME}
+hw.cpu.arch=${ABI}
+hw.cpu.ncore=${NCORE}
+hw.gpu.enabled=yes
+hw.gpu.mode=auto
+hw.keyboard=yes
+hw.initialOrientation=${ORIENTATION}
+hw.ramSize=${RAM}
+vm.heapSize=${HEAP}
+disk.dataPartition.size=${DATA}" > "${AVD_CONFIG_INI}"
+
+if [[ -z "${SKIN}" ]]; then
+  skinSettings="showDeviceFrame=no"
+else
+  skinSettings="showDeviceFrame=yes
+skin.dynamic=yes
+skin.name=${SKIN}
+skin.path=${AVD_IMG_DIR}/${ABI}/skins/${SKIN}"
+fi
+echo "${skinSettings}" >> "${AVD_CONFIG_INI}"
diff --git a/avd/resource/devices.xml b/avd/resource/devices.xml
new file mode 100644
index 0000000..fca0246
--- /dev/null
+++ b/avd/resource/devices.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<d:devices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:d="http://schemas.android.com/sdk/devices/5">
+    <d:device>
+        <d:name>Automotive (10" landscape)</d:name>
+        <d:id>aosp_car_10_landscape</d:id>
+        <d:manufacturer>Android</d:manufacturer>
+        <d:hardware>
+            <d:screen>
+                <d:screen-size>large</d:screen-size>
+                <d:diagonal-length>10.3</d:diagonal-length>
+                <d:pixel-density>tvdpi</d:pixel-density>
+                <d:screen-ratio>notlong</d:screen-ratio>
+                <d:dimensions>
+                    <d:x-dimension>1920</d:x-dimension>
+                    <d:y-dimension>1080</d:y-dimension>
+                </d:dimensions>
+                <d:xdpi>213</d:xdpi>
+                <d:ydpi>213</d:ydpi>
+                <d:touch>
+                    <d:multitouch>basic</d:multitouch>
+                    <d:mechanism>finger</d:mechanism>
+                    <d:screen-type>capacitive</d:screen-type>
+                </d:touch>
+            </d:screen>
+            <d:networking>
+                Bluetooth
+                Wifi
+                NFC
+            </d:networking>
+            <d:sensors>
+                LightSensor
+                GPS
+            </d:sensors>
+            <d:mic>true</d:mic>
+            <d:keyboard>nokeys</d:keyboard>
+            <d:nav>nonav</d:nav>
+            <d:ram unit="KiB">3774492</d:ram>
+            <d:buttons>soft</d:buttons>
+            <d:internal-storage unit="KiB">10255672</d:internal-storage>
+            <d:cpu>Generic CPU</d:cpu>
+            <d:gpu>Generic GPU</d:gpu>
+            <d:abi>
+                x86_64
+            </d:abi>
+            <d:dock/>
+            <d:power-type>plugged-in</d:power-type>
+        </d:hardware>
+        <d:software>
+            <d:api-level>-</d:api-level>
+            <d:live-wallpaper-support>false</d:live-wallpaper-support>
+            <d:bluetooth-profiles/>
+            <d:gl-version>2.0</d:gl-version>
+            <d:gl-extensions/>
+            <d:status-bar>true</d:status-bar>
+        </d:software>
+        <d:state name="Landscape" default="true">
+            <d:description>The device in landscape orientation</d:description>
+            <d:screen-orientation>land</d:screen-orientation>
+            <d:keyboard-state>keyssoft</d:keyboard-state>
+            <d:nav-state>nonav</d:nav-state>
+        </d:state>
+        <d:tag-id>android-automotive</d:tag-id>
+    </d:device>
+</d:devices>
diff --git a/avd/test_create_avd.sh b/avd/test_create_avd.sh
new file mode 100755
index 0000000..56937d3
--- /dev/null
+++ b/avd/test_create_avd.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Copyright (C) 2021 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.
+
+MY_NAME=$0
+SCRIPT_NAME=${MY_NAME##*/}
+SCRIPT_DIR=${MY_NAME%/$SCRIPT_NAME}
+
+echo "Create sdk_gcar_30.avd"
+AVD_IMG_NAME="sdk_gcar" \
+  ABI="x86_64" \
+  API_LEVEL=30 \
+  DEFAULT_DEVICE_XML="${SCRIPT_DIR}/resource/devices.xml" \
+  "${SCRIPT_DIR}/create_avd.sh"
+
+echo
+echo "Remove sdk_gcar_30.avd"
+rm -r /Users/samlin/.android/avd/sdk_gcar_30.avd || rm /Users/samlin/.android/avd/sdk_gcar_30.ini
+
+echo
+echo "Create sdk_gcar_30.avd again"
+AVD_IMG_NAME="sdk_gcar" \
+  ABI="x86_64" \
+  API_LEVEL=30 \
+  DEFAULT_DEVICE_XML="${SCRIPT_DIR}/resource/devices.xml" \
+  "${SCRIPT_DIR}/create_avd.sh"