152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project#!/bin/sh
252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
3291bb9f4682064867cf71e185d05b0527cd57087Marco NelissenLANG=C
4291bb9f4682064867cf71e185d05b0527cd57087Marco Nelissen
552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectif [ "$1" == "-h" ]
652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectthen
752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    cat <<- EOH
852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project		    Usage: $0 [-p] [folder]
952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project		      -p option prints out unused resources, otherwise a total count is printed
1052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project		      folder option causes only that app folder to be scanned, default is to scan all folders onder apps/
1152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project		EOH
1252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    exit
1352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectfi
1452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
1552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectshowall=no
1652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectif [ "$1" == "-p" ]
1752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectthen
1852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    showall=yes
1952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    shift
2052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectfi
2152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
2252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectapps=$1
2352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectif [ "$apps" == "" ]
2452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectthen
2552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    apps=$ANDROID_BUILD_TOP/packages/apps/*
2652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectfi
2752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
2852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectfor app in $apps
2952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectdo
3052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    echo '-----------------------------------------------------------'
316b0277d59bd04956e3f9c0db5717058e65c26a29Marco Nelissen    if [ "$app" == "." ]
326b0277d59bd04956e3f9c0db5717058e65c26a29Marco Nelissen    then
336b0277d59bd04956e3f9c0db5717058e65c26a29Marco Nelissen        app=$(pwd)
346b0277d59bd04956e3f9c0db5717058e65c26a29Marco Nelissen    fi
3552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    if [ -d $app/res ]
3652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    then
3752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        appname=$(basename $app)
38936e648ce98cb468ac02dc7e6ef9f7df897f03ffMarco Nelissen        iappname=$(grep LOCAL_PACKAGE_NAME $app/Android.mk | sed 's/.*:= *//')
3952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        resources=
404357bb8b8cd377b0a3c12eb2f270fabfd60fc1d5Marco Nelissen        for res in $(echo $app/res/* $(find $ANDROID_BUILD_TOP/vendor -type d -wholename $ANDROID_BUILD_TOP/vendor/*/$appname/res | grep overlay))
4152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        do
4252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            resources="$resources $(echo $res | grep -v '\-mcc\|[a-z]*-[a-z][a-z]$\|[a-z]*-[a-z][a-z]-.*')"
4352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        done
4452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        sources=$app/src
4552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if [ -d $app/tests ]
4652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        then
4752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            sources="$sources $app/tests"
4852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        fi
4952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if [ -d $app/samples ]
5052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        then
5152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            sources="$sources $app/samples"
5252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        fi
5352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
5452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        # find the R.java file that contains all the generated resource identifiers
55936e648ce98cb468ac02dc7e6ef9f7df897f03ffMarco Nelissen        rDotJava=$(find $ANDROID_BUILD_TOP/out/target/common/obj/APPS/${iappname}_intermediates/ -name R.java)
5652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
5752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        # Simplistically process the content of the file to get the names of all the constants,
5852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        # and try to find a reference to each constant.
59d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen
60d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen        # First take all the input files and concatenate them, removing newlines. This allows us to
61d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen        # find expressions that are broken up over multiple lines, i.e. R.drawable.\nsomeconstant
624357bb8b8cd377b0a3c12eb2f270fabfd60fc1d5Marco Nelissen        find $resources $sources $app/AndroidManifest.xml -type f -print |xargs cat | tr -d '\n ' > /tmp/everything$$
63d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen
64d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen        # Now look for each of the constants in the contatenated file.
6552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        for i in $(cat $rDotJava | grep "\w*=0x\d*" | sed 's/ *public static final int //' | sed 's/=0x.*//')
6652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        do
6752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            # Since periods in the names get translated to underscores in R.java, and you can actually
6852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            # refer to such constants from java by using an underscore instead of a period, we also
6952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            # replace all underscores with a pattern that will match periods and underscores.
7052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            p=$(echo $i | sed 's/_/[\\._]/g')
717d421c5b02943db80dee6103dbe40e6caa4fcfd0Marco Nelissen            echo $i $(grep -cw R\\..*\\.$i\\\|@style/$p\\\|@drawable/$p\\\|@anim/$p\\\|@color/$p\\\|@xml/$p\\\|@layout/$p\\\|@menu/$p\\\|@+id/$p\\\|@array/$p\\\|@string/$p\\\|@mipmap/$p\\\|@integer/$p\\\|@dimen/$p\\\|\[a-z\]\*:$p\\\|enumname=\"$p\\\|\<item\>$p\< < /tmp/everything$$)
7252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        done | grep " 0$" | {
73d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen            # this block gets as its input a list of constants for which no references were found, one per line
7452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            if [ "$showall" == "yes" ]
7552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            then
7652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                echo $app
7752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                cat
7852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            else
7952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                count=$(wc -l)
8052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                if [ "$count" != "0" ]
8152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                then
8252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                    echo $app: $count unused resources
8352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                fi
8452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            fi
8552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
86d0a241c3e8e520221befeb9c2865af65c216db20Marco Nelissen        rm /tmp/everything$$
8752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    fi
8852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectdone
89