Doze 변경 사항 (Android 6.0 -> Android 7.0)

Android 6.0에서 이미 Doze를 도입 했었다.

기기가 테이블 위나 서랍 안에 있는 등 유휴 상태일 때 앱이 CPU와 Network를 사용하는 작업을 지연 시키는 방식으로 배터리를 절약하는 시스템 모드를 말한다.

이제 Android N에서 Doze는 한걸음 더 나아가서 이동 중에도 배터리를 절약합니다. 화면이 일정 시간 동안 꺼져있고 기기의 플러그가 뽑혀있으면 Doze는 친숙한 일부 CPU 및 네트워크 제한을 앱에 적용합니다. 즉, 사용자가 기기를 주머니에 휴대하고 다닐 때도 배터리를 절약할 수 있습니다.

https://developer.android.com/preview/behavior-changes.html
https://developer.android.com/training/monitoring-device-state/doze-standby.html#assessing_your_app


Google IO 2016: Android Battery and Memory Optimizations


Project Svelte

Ashish Sharma
Tech lead of the Volta team inside Android

Meghan Desai
Product Manager on the Android framework team, working on battery life and memomry optimizations

Power consumption state는 크게 두가지로 나뉜다.

  • 첫 번째는 Screen ON 상태이고
  • 두 번째는 Screen OFF 상태이다.

대부분의 시간은 Screen OFF의 상태로 사람의 주머니에서 동작하므로 이 상태에 대해서 주목할 필요가 있다.

Screen OFF 상태에서는 CPU와 Radios가 주된 Power consumption을 차지 하게 된다.

이러한 Background process에 의한 Power consumption을 줄이기 위한 방법은 3가지가 있다.

  1. reduce all
    • Reduce all backgorund acitivity.
  2. defer
    • If background activity must be performed, defer it to when device is on charger.
  3. Coalesce
    • If it cannot be deferred, coalesce it with other background activity to reduce wakeup overhead.

Doze and App Standby in Marshmallow 

Question

If I used instant message app, then this app did not receive message for a long time. If so, it goes in app standby, then I might miss the incoming instant messages or video calls beacuse the app is in App Standby?

No your message go through. So for that use case, we as part of Doze and App Standby we launched something called a high-priority Google Cloud

High-priority GCM (now FCM) messages

  • Grant apps temporary wakelock and network access
  • For use cases requiring immediate notification to user
  • Normal FCM messages batched to maintenance window

Doze & App Standby disabled by default in AOSP Requres Firebase Cloud Message (in Google Play Services) or alternative cloud push messaging service

Foreground services

  • Exempt from Doze and App Standby
  • For use cases such as music playback

Alarm APIs

  • For alarms that need to trigger while device is in Doze

Whitelist

  • Users can add app to whitelist via Settings
  • Apps can prompt users at runtime if they meet acceptable use case requirements and pass Play Store review


Battery Current 정보를 알아내는 위치



Nexus 4의 경우 Qualcomm PM 8921 

Nexus 5의 경우 Qualcomm PM 8941

Nexus 5x의 경우 Qualcomm PMI8994 Power Management IC (Also found in LG G4, HTC One M9, and OnePlus Two)

https://www.ifixit.com/Teardown/Nexus+5X+Teardown/51318


위 두개의 Internal Charge Controller Circuit이 존재하기 떄문에

Linux Kernel을 통해서 Current drain 정보 획득이 가능 하다.


획득된 정보의 단위는 mA 이다.

양수면 충전 중이고

음수면 방전 중이다.




cat /sys/class/power_supply/battery/current_now


아래의 오픈 소스 앱을 이용해도 대고

코드를 분석하면 앱도 만들 수 있다.

https://code.google.com/p/currentwidget/


Stack over flow 사이트

http://stackoverflow.com/questions/2439619/getting-the-battery-current-values-for-the-android-phone



GPU 정보


Gpubusy

adb -d shell cat /sys/class/kgsl/kgsl-3d0/gpubusy | awk '{print $1 / ($2+1)}‘

Utilization (0~1)


ADB_Over_network을 reboot시 초기화 하지 않는 방법


전체적인 System Properties와 preference와의 일관성 유지 및 사용자와의 상호작용 그리고 초기화 매커니즘은 아래의 그림과 같다.



Android Preference 구조 그림.pptx





□ setprop persist.adb.tcp.port 5555

  • 위 명령을 adb를 이용해서 치면, 재부팅 시에도 port가 5555로 설정 되어 짐.
  • 플랫폼을 수정할 필요 없는 가장 간단한 방법
  • adbd 자체에서, 이 기능을 지원함.
  • 원상태 복구를 위해서는, setprop을 다시 직접 쳐야한다는 단점, 발생 왜냐하면, Adb deamon은 persist option에는 반응하지 않음.


□ adbd을 수정


소스코드 위치: system/core/adb/adb.c

// adb_over_network ON
property_get("service.adb.tcp.port",value,"5555");
property_get("persist.adb.tcp.port",value,"");

// adb_over_network OFF
property_get("service.adb.tcp.port",value,"");
property_get("persist.adb.tcp.port",value,"");

핵심은 뒤의 것은 default라는 것이다. 값이 존재하지 않으면, ""를 기록 하게 됨.
""로 설정하면, SystemServer에서 Empty로 인식해서, Default 값을 기록 하게 됨 (Settings App에서의 일관성 유지).
단점: 원상 복구를 위해서는 직접 property를 변경 해야함.

□ Settings App과 System Server 수정


Settings App: 사용자와의 상호작용을 담당. 설정값에 대한 입력 과 출력

System Server: System Properties로부터 값을 읽어와서 System Preference값을 그에 맞추어 변경함. 즉, 서로다른 두 레벨간의 일관성을 유지시켜 줌.

추가로, ContentObserver를 등록 시켜서, System Preference가 변경되어 지면, 그것을 System Properties에 적용 시킴.


framework/base -> service/SystemServer.java


//해당 코드는 Content가 변경 되어지면, 호출 되어 짐. (e.g: 사용자가 설정을 변경 했을 때)

 91     private class AdbPortObserver extends ContentObserver {

 92         public AdbPortObserver() {

 93             super(null);

 94         }

 95         @Override

 96         public void onChange(boolean selfChange) {

 97             int adbPort = Settings.Secure.getInt(mContentResolver,

 98                 Settings.Secure.ADB_PORT, 0);

 99             // setting this will control whether ADB runs on TCP/IP or USB

100             SystemProperties.set("service.adb.tcp.port", Integer.toString(adbPort));

// 결국, 위 코드가 Setting.Secure(java)의 내용을 SystemProperties (native) 영역으로 // 전송하는 역할을 함.

101             Log.e("SystemServer:jaynux","adbPort: "+ adbPort);

102         }

103     }



→ 새로운 옵션 추가
Settings app에 ADBTCPIP_ENABLED 옵션 추가.
위 추가한 옵션을 이용해서, TCP Port를 초기화 할지, 아니면 다른 값으로 설정할지가 결정 됨.

→ System Properties는 변경 되지 않음
system properties로부터 get 한다. 핵심은 get만 한다는 것이다. 
결국, system properties는 변경 되어 지지 않는다. 따라서, get한 내용을, 그저 putInt를 통해서 System preference에 반영하는 작업만을 한다.

→ Default 동작의 의미
service.adb.tcp.port에 대해서 값을 얻어오고, 없을 경우 -1을 default로 하게 됨.
get은 native code 이다. default가 되어지는 경우는, null이거나, empty의 경우.
adbd은 해당 값을 ""로 설정하기 때문에, 항상 default 값이 System Preference에 반영됨.
그래서, Settings app으로 확인해 보면, CheckBox가 정상적으로 잘 표현되어 짐을 알 수 있다.
하지만, 아무리 Check 되어져 있다고 해도, 설령 이 값을 변경 한다고해도, Observer는 그 후에, 
등록 되어 지므로, system properties는 변경 안됨


→ Properties와 Preference의 일관성 유지를 위해서 사용한 방법
SystemProperties.set()을 이용해서 직접 Properties를 설정해주면 된다.
persist를 쓰면 편하지만, 현재 adbd는 persist 값을 부팅시에만 반영하므로, 동작중에 변경을 하더라도, adbd은 계속해서 TCP/IP 모드로 동작하므로, 불편함이 존재 한다. 
결론적으로, adbd의 변경 없이, 자유롭게 사용하기 위해서, service.adb.tcp.port를 사용하며, set()으로 직접 설정 한다.



System property를 Setting 하는 방법은 3가지가 있습니다.


1. Native

int property_get(const char *key, char *value, const char *default_value);

int property_set(const char *key, const char *value);

2. Java

String SystemProperties.get(String key);

SystemProperties.set(String key,String value);

3. adb 명령

adb shell 

root# setprop key value

root# getprop key



import android.util.Log 



String TAG = "tag id"


Log.e(TAG,"message");

■ 함수 분석


148     public boolean sameAs(IChimpImage other, double percent) {
149         BufferedImage otherImage = other.getBufferedImage();
150         BufferedImage myImage = getBufferedImage();
151
152         // Easy size check
153         if (otherImage.getWidth() != myImage.getWidth()) {
154             return false;
155         }
156         if (otherImage.getHeight() != myImage.getHeight()) {
157             return false;
158         }
159
160         int[] otherPixel = new int[1];
161         int[] myPixel = new int[1];
162
163         int width = myImage.getWidth();
164         int height = myImage.getHeight();
165
166         int numDiffPixels = 0;
167         // Now, go through pixel-by-pixel and check that the images are the same;
168         for (int y = 0; y < height; y++) {
169             for (int x = 0; x < width; x++) {
170                 if (myImage.getRGB(x, y) != otherImage.getRGB(x, y)) {
171                     numDiffPixels++;
172                 }
173             }
174         }
175         double numberPixels = (height * width);
176         double diffPercent = numDiffPixels / numberPixels;
177         return percent <= 1.0 - diffPercent;


특징

1) Width와 Height가 틀리다면, 비교가 실패한다.

2) 한 픽셀씩 비교한다음에, 결국 numDiffPixels를 하나씩 증가 시킨다.

3) diffPercent = numDiffPixels / numberPixels

4) percent <= 1.0 - diffPercent



□ 1단계: 샘플 코드


아래의 코드를 실행하면 된다. 단, monkeyrunner의 버전이 최신 SDK가 아니라면 


나의 경우, 가장 오래된 SDK 버전도 가능 했다 (nexus one을 위한 버전)


MonkeyImage.loadFromFile에서 Error가 발생 한다.

AttributeError: type object 'com.android.monkeyrunner.MonkeyRunner' has no attribute 'loadImageFromFile'


현재 버전이 loadImageFromFile 히든 함수를 지원 하는지 알 수 있는 방법.

아래의 코드를 넣어서 실행 시켜 보면 알 수 있다.

for m in [MonkeyRunner, MonkeyDevice, MonkeyImage]:
       print "%s:\n    %s\n"%(m.__name__, dir(m))


#! /usr/bin/env monkeyrunner

import sys
import subprocess
from com.android.monkeyrunner
import MonkeyRunner, MonkeyDevice, MonkeyImage

TIMEOUT = 30
SERIALNO = 'emulator-5554'
REF = 'reference.png'
SCR = 'screenshot.png'
CMP = 'comparison.png'
ACCEPTANCE = 0.9

device = None


def testDropWidgetIntoFourthRow():
    reference = MonkeyImage.loadFromFile(REF)
    print "moving widget..."
    device.drag((230, 300), (230, 600), 2.0, 125)
    MonkeyRunner.sleep(3)
    screenshot = device.takeSnapshot()
    screenshot.writeToFile(SCR)
    if not screenshot.sameAs(reference, ACCEPTANCE):
       print "comparison failed, getting visual comparison..."
       subprocess.call(["/usr/bin/compare", REF, SCR, CMP])

def main():
    global device
    print "waiting for connection..."
    device = MonkeyRunner.waitForConnection(TIMEOUT, SERIALNO)
    if device:
       testDropWidgetIntoFourthRow()


if __name__ == '__main__':
     main()

위 코드는 Diego(테스팅 대가)가 monkeyImage에 loadFromFile이라는 함수를 임의로 추가해서 사용한 코드이다.

따라서 monkeyrunner 수정 없이는, 동작하지 않는 코드이다.



필자는 위코드를 아래와같이 변경해서 사용함.


#! /usr/bin/env monkeyrunner
import sys
import subprocess

from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage

TIMEOUT = 30
SERIALNO = 'emulator-5554'
REF = '../ImageStore/GameActivityDesire.png'
SCR = '../ImageStore/GameActivityGalaxyNexus_Resize.png'

CMP = 'comparison.png'
ACCEPTANCE = 0.9
device = None


def testDropWidgetIntoFourthRow():

#reference = MonkeyImage.loadFromFile(REF)
reference = MonkeyRunner.loadImageFromFile(REF)

#source = MonkeyImage.loadFromFile(SCR)
source = MonkeyRunner.loadImageFromFile(SCR)

if not source.sameAs(reference, ACCEPTANCE):
print "comparison failed, getting visual comparison..."
subprocess.call(["/usr/bin/compare", REF, SCR, CMP])



def main():
# for m in [MonkeyRunner, MonkeyDevice, MonkeyImage]:
# print "%s:\n %s\n"%(m.__name__, dir(m))
testDropWidgetIntoFourthRow()

if __name__ == '__main__':
main()



/*
이 코드의 특징은 takeSnapshot()의 사용없이, loadImageFromFile 함수만을 이용해서 기존에 저장된

이미지들간의 유사도를 sameAs 함수로 알아보는 것이다.

*/


Trouble shooting


리플랙트 에러가 발생하는 경우.

Monkeyrunner at java.lang.reflect.Method.invoke(Method.java:597)


해결방법

1) 비교할려는 두개의 이미지의 해상도가 같은지를 확인해라!

2) 이미지의 경로가 맞는지 확인해라! loadImageFromFile()함수는 경로가 틀려도 어떠한 에러도

발생 시키지 않는다.

3) monkeyrunner의 버전이 너무 낮은건 아닌지 확인 해라!




□ 2단계: 최신 monkeyrunner 구하기


정확히 릴리즈 몇부터 monkeyrunner의 히든 API로 loadFromFile이 존재하는지는 모르겠다.


분석에 사용된 Android version: AOSP-4.2_r2


디렉터리 위치: sdk/android/chimpchat/core/ChumpImageBase.java



공개된 API 리스트들이다.


MonkeyImage



string convertToBytes (string format)
Converts the current image to a particular format and returns it as a string that you can then access as an iterable of binary bytes.
tuple getRawPixel (integer x, integer y)
Returns the single pixel at the image location (x,y), as an a tuple of integer, in the form (a,r,g,b).
integer getRawPixelInt (integer x, integer y)
Returns the single pixel at the image location (x,y), as a 32-bit integer.
MonkeyImage getSubImage (tuple rect)
Creates a new MonkeyImage object from a rectangular selection of the current image.
boolean sameAs (MonkeyImage other, float percent)
Compares this MonkeyImage object to another and returns the result of the comparison. The percent argument specifies the percentage difference that is allowed for the two images to be "equal".
void writeToFile (string path, string format)
Writes the current image to the file specified by filename, in the format specified by format.



숨겨진 API


DictInit [MonkeyImage]
MonkeyImage [MonkeyImage]
getImpl [MonkeyImage]

convertToBytes [MonkeyImage]
writeToFile [MonkeyImage]
getRawPixel [MonkeyImage]
getRawPixelInt [MonkeyImage]
sameAs [MonkeyImage]
getSubImage [MonkeyImage]



□ 3단계: monkeyrunner를 수정해서 사용하기.


chimpchat 프로젝트에 생각보다 많은 좋은 API들이 있다. 하지만 이것을 사용 할 수 있는지는 연구를 해봐야한다. API가 어떤식으로 노출되어지는지 분석을 해봐야 할것 같다.






Android.mk variables


These are the variables that you'll commonly see in Android.mk files, listed alphabetically.


But first, a note on variable naming:


    LOCAL_ - These variables are set per-module. They are cleared by the include $(CLEAR_VARS) line, so you can rely on them being empty after including that file. Most of the variables you'll use in most modules are LOCAL_ variables.

    PRIVATE_ - These variables are make-target-specific variables. That means they're only usable within the commands for that module. It also means that they're unlikely to change behind your back from modules that are included after yours. This link to the make documentation describes more about target-specific variables. Please note that there are a couple of these laying around the tree that aren't prefixed with PRIVATE_. It is safe, and they will be fixed as they are discovered. Sorry for the confusion.

    INTERNAL_ - These variables are critical to functioning of the build system, so you shouldn't create variables named like this, and you probably shouldn't be messing with these variables in your makefiles.

    HOST_ and TARGET_ - These contain the directories and definitions that are specific to either the host or the target builds. Do not set variables that start with HOST_ or TARGET_ in your makefiles.

    BUILD_ and CLEAR_VARS - These contain the names of well-defined template makefiles to include. Some examples are CLEAR_VARS and BUILD_HOST_PACKAGE.

    Any other name is fair-game for you to use in your Android.mk. However, remember that this is a non-recursive build system, so it is possible that your variable will be changed by another Android.mk included later, and be different when the commands for your rule / module are executed.


LOCAL_ASSET_FILES


In Android.mk files that include $(BUILD_PACKAGE) set this to the set of files you want built into your app. Usually:


LOCAL_ASSET_FILES += $(call find-subdir-assets)


This will probably change when we switch to ant for the apps' build system.

LOCAL_CC


If you want to use a different C compiler for this module, set LOCAL_CC to the path to the compiler. If LOCAL_CC is blank, the appropriate default compiler is used.

LOCAL_CXX


If you want to use a different C++ compiler for this module, set LOCAL_CXX to the path to the compiler. If LOCAL_CXX is blank, the appropriate default compiler is used.

LOCAL_CFLAGS


If you have additional flags to pass into the C or C++ compiler, add them here. For example:


LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

LOCAL_CPPFLAGS


If you have additional flags to pass into only the C++ compiler, add them here. For example:


LOCAL_CPPFLAGS += -ffriend-injection

LOCAL_CPPFLAGS is guaranteed to be after LOCAL_CFLAGS on the compile line, so you can use it to override flags listed in LOCAL_CFLAGS.

LOCAL_CPP_EXTENSION


If your C++ files end in something other than ".cpp", you can specify the custom extension here. For example:


LOCAL_CPP_EXTENSION := .cc

Note that all C++ files for a given module must have the same extension; it is not currently possible to mix different extensions.

LOCAL_NO_DEFAULT_COMPILER_FLAGS


Normally, the compile line for C and C++ files includes global include paths and global cflags. If LOCAL_NO_DEFAULT_COMPILER_FLAGS is non-empty, none of the default includes or flags will be used when compiling C and C++ files in this module. LOCAL_C_INCLUDES, LOCAL_CFLAGS, and LOCAL_CPPFLAGS will still be used in this case, as will any DEBUG_CFLAGS that are defined for the module.

LOCAL_COPY_HEADERS


This will be going away.


The set of files to copy to the install include tree. You must also supply LOCAL_COPY_HEADERS_TO.


This is going away because copying headers messes up the error messages, and may lead to people editing those headers instead of the correct ones. It also makes it easier to do bad layering in the system, which we want to avoid. We also aren't doing a C/C++ SDK, so there is no ultimate requirement to copy any headers.

LOCAL_COPY_HEADERS_TO


This will be going away.


The directory within "include" to copy the headers listed in LOCAL_COPY_HEADERS to.


This is going away because copying headers messes up the error messages, and may lead to people editing those headers instead of the correct ones. It also makes it easier to do bad layering in the system, which we want to avoid. We also aren't doing a C/C++ SDK, so there is no ultimate requirement to copy any headers.

LOCAL_C_INCLUDES


Additional directories to instruct the C/C++ compilers to look for header files in. These paths are rooted at the top of the tree. Use LOCAL_PATH if you have subdirectories of your own that you want in the include paths. For example:


LOCAL_C_INCLUDES += extlibs/zlib-1.2.3

LOCAL_C_INCLUDES += $(LOCAL_PATH)/src


You should not add subdirectories of include to LOCAL_C_INCLUDES, instead you should reference those files in the #include statement with their subdirectories. For example:


#include <utils/KeyedVector.h>

not #include <KeyedVector.h>


There are some components that are doing this wrong, and should be cleaned up.

LOCAL_MODULE_TAGS


Set LOCAL_MODULE_TAGS to any number of whitespace-separated tags. If the tag list is empty or contains droid, the module will get installed as part of a make droid. Modules with the tagshell_$(TARGET_SHELL) will also be installed. Otherwise, it will only get installed by running make <your-module> or with the make all pseudotarget.

LOCAL_REQUIRED_MODULES


Set LOCAL_REQUIRED_MODULES to any number of whitespace-separated module names, like "libblah" or "Email". If this module is installed, all of the modules that it requires will be installed as well. This can be used to, e.g., ensure that necessary shared libraries or providers are installed when a given app is installed.

LOCAL_FORCE_STATIC_EXECUTABLE


If your executable should be linked statically, set LOCAL_FORCE_STATIC_EXECUTABLE:=true. There is a very short list of libraries that we have in static form (currently only libc). This is really only used for executables in /sbin on the root filesystem.

LOCAL_GENERATED_SOURCES


Files that you add to LOCAL_GENERATED_SOURCES will be automatically generated and then linked in when your module is built. See the Custom Tools template makefile for an example.

LOCAL_JAVACFLAGS


If you have additional flags to pass into the javac compiler, add them here. For example:


LOCAL_JAVACFLAGS += -Xlint:deprecation

LOCAL_JAVA_LIBRARIES


When linking Java apps and libraries, LOCAL_JAVA_LIBRARIES specifies which sets of java classes to include. Currently there are two of these: core and framework. In most cases, it will look like this:


LOCAL_JAVA_LIBRARIES := core framework


Note that setting LOCAL_JAVA_LIBRARIES is not necessary (and is not allowed) when building an APK with "include $(BUILD_PACKAGE)". The appropriate libraries will be included automatically.

LOCAL_LDFLAGS


You can pass additional flags to the linker by setting LOCAL_LDFLAGS. Keep in mind that the order of parameters is very important to ld, so test whatever you do on all platforms.

LOCAL_LDLIBS


LOCAL_LDLIBS allows you to specify additional libraries that are not part of the build for your executable or library. Specify the libraries you want in -lxxx format; they're passed directly to the link line. However, keep in mind that there will be no dependency generated for these libraries. It's most useful in simulator builds where you want to use a library preinstalled on the host. The linker (ld) is a particularly fussy beast, so it's sometimes necessary to pass other flags here if you're doing something sneaky. Some examples:


LOCAL_LDLIBS += -lcurses -lpthread

LOCAL_LDLIBS += -Wl,-z,origin

LOCAL_NO_MANIFEST


If your package doesn't have a manifest (AndroidManifest.xml), then set LOCAL_NO_MANIFEST:=true. The common resources package does this.

LOCAL_PACKAGE_NAME


LOCAL_PACKAGE_NAME is the name of an app. For example, Dialer, Contacts, etc. This will probably change or go away when we switch to an ant-based build system for the apps.

LOCAL_PATH


The directory your Android.mk file is in. You can set it by putting the following as the first line in your Android.mk:


LOCAL_PATH := $(my-dir)


The my-dir macro uses the MAKEFILE_LIST variable, so you must call it before you include any other makefiles. Also, consider that any subdirectories you inlcude might reset LOCAL_PATH, so do your own stuff before you include them. This also means that if you try to write several include lines that reference LOCAL_PATH, it won't work, because those included makefiles might reset LOCAL_PATH.

LOCAL_POST_PROCESS_COMMAND


For host executables, you can specify a command to run on the module after it's been linked. You might have to go through some contortions to get variables right because of early or late variable evaluation:


module := $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)

LOCAL_POST_PROCESS_COMMAND := /Developer/Tools/Rez -d __DARWIN__ -t APPL\

       -d __WXMAC__ -o $(module) Carbon.r

LOCAL_PREBUILT_EXECUTABLES


When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to executables that you want copied. They're located automatically into the right bin directory.

LOCAL_PREBUILT_LIBS


When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to libraries that you want copied. They're located automatically into the right lib directory.

LOCAL_SHARED_LIBRARIES


These are the libraries you directly link against. You don't need to pass transitively included libraries. Specify the name without the suffix:


LOCAL_SHARED_LIBRARIES := \

    libutils \

    libui \

    libaudio \

    libexpat \

    libsgl

LOCAL_SRC_FILES


The build system looks at LOCAL_SRC_FILES to know what source files to compile -- .cpp .c .y .l .java. For lex and yacc files, it knows how to correctly do the intermediate .h and .c/.cpp files automatically. If the files are in a subdirectory of the one containing the Android.mk, prefix them with the directory name:


LOCAL_SRC_FILES := \

    file1.cpp \

    dir/file2.cpp

LOCAL_STATIC_LIBRARIES


These are the static libraries that you want to include in your module. Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.


LOCAL_STATIC_LIBRARIES := \

    libutils \

    libtinyxml

LOCAL_MODULE


LOCAL_MODULE is the name of what's supposed to be generated from your Android.mk. For exmample, for libkjs, the LOCAL_MODULE is "libkjs" (the build system adds the appropriate suffix -- .so .dylib .dll). For app modules, use LOCAL_PACKAGE_NAME instead of LOCAL_MODULE. We're planning on switching to ant for the apps, so this might become moot.

LOCAL_MODULE_PATH


Instructs the build system to put the module somewhere other than what's normal for its type. If you override this, make sure you also set LOCAL_UNSTRIPPED_PATH if it's an executable or a shared library so the unstripped binary has somewhere to go. An error will occur if you forget to.


See Putting modules elsewhere for more.

LOCAL_UNSTRIPPED_PATH


Instructs the build system to put the unstripped version of the module somewhere other than what's normal for its type. Usually, you override this because you overrodeLOCAL_MODULE_PATH for an executable or a shared library. If you overrode LOCAL_MODULE_PATH, but not LOCAL_UNSTRIPPED_PATH, an error will occur.


See Putting modules elsewhere for more.

LOCAL_WHOLE_STATIC_LIBRARIES


These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. This is mostly useful if you want to add a static library to a shared library and have the static library's content exposed from the shared library.


LOCAL_WHOLE_STATIC_LIBRARIES := \

    libsqlite3_android

LOCAL_YACCFLAGS


Any flags to pass to invocations of yacc for your module. A known limitation here is that the flags will be the same for all invocations of YACC for your module. This can be fixed. If you ever need it to be, just ask.


LOCAL_YACCFLAGS := -p kjsyy

Implementation Details


You should never have to touch anything in the config directory unless you're adding a new platform, new tools, or adding new features to the build system. In general, please consult with the build system owner(s) (android-build-team) before you go mucking around in here. That said, here are some notes on what's going on under the hood.

Environment Setup / buildspec.mk Versioning


In order to make easier for people when the build system changes, when it is necessary to make changes to buildspec.mk or to rerun the environment setup scripts, they contain a version number in the variable BUILD_ENV_SEQUENCE_NUMBER. If this variable does not match what the build system expects, it fails printing an error message explaining what happened. If you make a change that requires an update, you need to update two places so this message will be printed.


    In config/envsetup.make, increment the CORRECT_BUILD_ENV_SEQUENCE_NUMBER definition.

    In buildspec.mk.default, update the BUILD_ENV_SEQUENCE_DUMBER definition to match the one in config/envsetup.make


The scripts automatically get the value from the build system, so they will trigger the warning as well.


Additional makefile variables


You probably shouldn't use these variables. Please consult android-build-team before using them. These are mostly there for workarounds for other issues, or things that aren't completely done right.

LOCAL_ADDITIONAL_DEPENDENCIES


If your module needs to depend on anything else that isn't actually built in to it, you can add those make targets to LOCAL_ADDITIONAL_DEPENDENCIES. Usually this is a workaround for some other dependency that isn't created automatically.

LOCAL_BUILT_MODULE


When a module is built, the module is created in an intermediate directory then copied to its final location. LOCAL_BUILT_MODULE is the full path to the intermediate file. See LOCAL_INSTALLED_MODULE for the path to the final installed location of the module.

LOCAL_HOST


Set by the host_xxx.make includes to tell base_rules.make and the other includes that we're building for the host. Kenneth did this as part of openbinder, and I would like to clean it up so the rules, includes and definitions aren't duplicated for host and target.

LOCAL_INSTALLED_MODULE


The fully qualified path name of the final location of the module. See LOCAL_BUILT_MODULE for the location of the intermediate file that the make rules should actually be constructing.

LOCAL_REPLACE_VARS


Used in some stuff remaining from the openbinder for building scripts with particular values set,

LOCAL_SCRIPTS


Used in some stuff remaining from the openbinder build system that we might find handy some day.

LOCAL_MODULE_CLASS


Which kind of module this is. This variable is used to construct other variable names used to locate the modules. See base_rules.make and envsetup.make.

LOCAL_MODULE_NAME


Set to the leaf name of the LOCAL_BUILT_MODULE. I'm not sure, but it looks like it's just used in the WHO_AM_I variable to identify in the pretty printing what's being built.

LOCAL_MODULE_SUFFIX


The suffix that will be appended to LOCAL_MODULE to form LOCAL_MODULE_NAME. For example, .so, .a, .dylib.

LOCAL_STRIP_MODULE


Calculated in base_rules.make to determine if this module should actually be stripped or not, based on whether LOCAL_STRIPPABLE_MODULE is set, and whether the combo is configured to ever strip modules. With Iliyan's stripping tool, this might change.

LOCAL_STRIPPABLE_MODULE


Set by the include makefiles if that type of module is strippable. Executables and shared libraries are.

LOCAL_SYSTEM_SHARED_LIBRARIES


Used while building the base libraries: libc, libm, libdl. Usually it should be set to "none," as it is in $(CLEAR_VARS). When building these libraries, it's set to the ones they link against. For example, libc, libstdc++ and libdl don't link against anything, and libm links against libc. Normally, when the value is none, these libraries are automatically linked in to execu

+ Recent posts