#!/bin/bash # Script to swap core networking modules in a GMS userdebug device to AOSP modules, by remounting # the system partition and replacing module prebuilts. This is only to be used for local testing, # and should only be used on userdebug devices that support "adb root" and remounting the system # partition using overlayfs. The setup wizard should be cleared before running the script. # # Usage: aospify_device.sh [device_serial] # # Reset with "adb enable-verity", then wiping data (from Settings, or: # "adb reboot bootloader && fastboot erase userdata && fastboot reboot"). # Some devices output errors like "Overlayfs teardown failed" on "enable-verity" but it still works # (/mnt/scratch should be deleted). # # This applies to NetworkStack, CaptivePortalLogin, dnsresolver, tethering, cellbroadcast modules, # which generally need to be preloaded together (core networking modules + cellbroadcast which # shares its certificates with NetworkStack and CaptivePortalLogin) # # This allows device manufacturers to test their changes in AOSP modules, running them on their # own device builds, before contributing contributing the patches to AOSP. After running this script # once AOSP modules can be quickly built and updated on the prepared device with: # m NetworkStack # adb install --staged $ANDROID_PRODUCT_OUT/system/priv-app/NetworkStack/NetworkStack.apk \ # adb reboot # or for APEX modules: # m com.android.tethering deapexer # $ANDROID_HOST_OUT/bin/deapexer decompress --input $ANDROID_PRODUCT_OUT/system/apex/com.android.tethering.capex --output /tmp/decompressed.apex # adb install /tmp/decompressed.apex && adb reboot # # This has been tested on Android T and Android U Pixel devices. On recent (U+) devices, it requires # setting a released target SDK (for example target_sdk_version: "34") in # packages/modules/Connectivity/service/ServiceConnectivityResources/Android.bp before building. set -e function push_apex { local original_apex_name=$1 local aosp_apex_name=$2 if $ADB_CMD shell ls /system/apex/$original_apex_name.capex 1>/dev/null 2>/dev/null; then $ADB_CMD shell rm /system/apex/$original_apex_name.capex $ADB_CMD push $ANDROID_PRODUCT_OUT/system/apex/$aosp_apex_name.capex /system/apex/ else rm -f /tmp/decompressed_$aosp_apex_name.apex $ANDROID_HOST_OUT/bin/deapexer decompress --input $ANDROID_PRODUCT_OUT/system/apex/$aosp_apex_name.capex --output /tmp/decompressed_$aosp_apex_name.apex if ! $ADB_CMD shell ls /system/apex/$original_apex_name.apex 1>/dev/null 2>/dev/null; then # Filename observed on some phones, even though it is not actually compressed original_apex_name=${original_apex_name}_compressed fi $ADB_CMD shell rm /system/apex/$original_apex_name.apex $ADB_CMD push /tmp/decompressed_$aosp_apex_name.apex /system/apex/$aosp_apex_name.apex rm /tmp/decompressed_$aosp_apex_name.apex fi } function push_apk { local app_type=$1 local original_apk_name=$2 local aosp_apk_name=$3 $ADB_CMD shell rm /system/$app_type/$original_apk_name/$original_apk_name*.apk $ADB_CMD push $ANDROID_PRODUCT_OUT/system/$app_type/$aosp_apk_name/$aosp_apk_name.apk /system/$app_type/$original_apk_name/ } NETWORKSTACK_AOSP_SEPOLICY_KEY="\ <\/signer>" DEVICE=$1 ADB_CMD="adb -s $DEVICE" if [ -z "$DEVICE" ]; then echo "Usage: aospify_device.sh [device_serial]" exit 1 fi if [ -z "$ANDROID_BUILD_TOP" ]; then echo "Run build/envsetup.sh first to set ANDROID_BUILD_TOP" exit 1 fi if ! $ADB_CMD wait-for-device shell pm path com.google.android.networkstack 1>/dev/null 2>/dev/null; then echo "This device is already not using GMS modules" exit 1 fi read -p "This script is only for test purposes and highly likely to make your device unusable. \ Continue ? " prompt if [[ $prompt != "y" ]] then exit 0 fi cd $ANDROID_BUILD_TOP source build/envsetup.sh lunch aosp_arm64-trunk_staging-userdebug m NetworkStack CaptivePortalLogin com.android.tethering com.android.cellbroadcast \ com.android.resolv deapexer \ out/target/product/generic_arm64/system/etc/selinux/plat_mac_permissions.xml \ out/target/product/generic_arm64/system/etc/permissions/com.android.networkstack.xml $ADB_CMD root $ADB_CMD remount $ADB_CMD reboot echo "Waiting for boot..." until [[ $($ADB_CMD wait-for-device shell getprop sys.boot_completed) == 1 ]]; do sleep 1; done $ADB_CMD root $ADB_CMD remount push_apk priv-app NetworkStackGoogle NetworkStack push_apk app CaptivePortalLoginGoogle CaptivePortalLogin push_apex com.google.android.tethering com.android.tethering push_apex com.google.android.cellbroadcast com.android.cellbroadcast push_apex com.google.android.resolv com.android.resolv # Replace the network_stack key used to set its sepolicy context rm -f /tmp/pulled_plat_mac_permissions.xml $ADB_CMD pull /system/etc/selinux/plat_mac_permissions.xml /tmp/pulled_plat_mac_permissions.xml sed_replace='s/<\/signer>/'$NETWORKSTACK_AOSP_SEPOLICY_KEY'/' sed -E "$sed_replace" /tmp/pulled_plat_mac_permissions.xml | $ADB_CMD shell 'cat > /system/etc/selinux/plat_mac_permissions.xml' rm /tmp/pulled_plat_mac_permissions.xml # Update the networkstack privapp-permissions allowlist rm -f /tmp/pulled_privapp-permissions.xml networkstack_permissions=/system/etc/permissions/GoogleNetworkStack_permissions.xml if ! $ADB_CMD shell ls $networkstack_permissions 1>/dev/null 2>/dev/null; then networkstack_permissions=/system/etc/permissions/privapp-permissions-google.xml fi $ADB_CMD pull $networkstack_permissions /tmp/pulled_privapp-permissions.xml # Remove last line, and the permissions for com.google.android.networkstack sed -nE '1,/<\/permissions>/p' /tmp/pulled_privapp-permissions.xml \ | sed -E '/com.google.android.networkstack/,/privapp-permissions/d' > /tmp/modified_privapp-permissions.xml # Add the AOSP permissions and re-add the line sed -nE '/com.android.networkstack/,/privapp-permissions/p' $ANDROID_PRODUCT_OUT/system/etc/permissions/com.android.networkstack.xml \ >> /tmp/modified_privapp-permissions.xml echo '' >> /tmp/modified_privapp-permissions.xml $ADB_CMD push /tmp/modified_privapp-permissions.xml $networkstack_permissions rm /tmp/pulled_privapp-permissions.xml /tmp/modified_privapp-permissions.xml echo "Done modifying, rebooting" $ADB_CMD reboot