Android Framework Audio Service Analysis

AudioManager.java -> AudioService.java (Java Binder)

AudioManager provides an interface in SDK for Audio service. 
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
AudioManager(.java) calls functions of AudioService(.java) through Java Binder. AudioService itself is a hidden class in framework, its interface is not exposed in SDK directly.

AudioService.java -> AudioSystem.java + android_media_AudioSystem.cpp (JNI)

AudioService call functions of AudioSystem which is actually a container of JNI calls. The JNI calls are implemented in android_media_AudioSystem.cpp

android_media_AudioSystem.cpp 

  • Located under ../frameworks/base/core/jni. It is named according to its counterpart's full name, android.media.AudioSystem.
  • Android.mk builds it as a part of module libandroid_runtime.so, which is loaded somewhere ( probably LoadClass.java ) - System.loadLibrary( "android_runtime" );

android_media_AudioSystem.cpp  -> AudioSystem.cpp

The main purpose of android_media_AudioSystem.cpp is to conform with JNI. It delegates most of its jobs to av/media/libmedia/AudioSystem.cpp

AudioSystem.cpp -> AudioFlinger.cpp (C++ Binder )

AudioSystem.cpp acts as a low-level facade talking to other processes which provide the final implementation of audio service. The main one is AudioFlinger.
binder = sm->getService(String16("media.audio_flinger"));
gAudioFlinger = interface_cast<IAudioFlinger>(binder);

"Open Hardware" with Linux

This micro micro linux machine looks very nice. :-)

( Beaglebone Black)



Troubleshooting CDPATH problem in building AOSP with MacBook

Build Environment

Macbook with 2.2G core i7 + 8G RAM
  • OS X 10.9.5
  • GNU Make 3.81
  • Python 2.7.5
  • Java 1.7.0_71
  • git 1.9.3 ( Apple git-50 )
  • gcc 4.2.1

Problem

With all Android source in /Volumes/Opensource/android/aosp, trying to make -j4, get error message

make: *** No rule to make target     `frameworks/base//Volumes/Opensource/android/aosp/frameworks/base', needed by `out/target/common/docs/api-stubs-timestamp'.  Stop.

Troubleshooting process

This is just the way of thinking, not a step by step guide.

First, where is target out/target/common/docs/api-stubs-timestamp defined.

Apparently frameworks/base//Volumes/Opensource/android/aosp/frameworks/base is an incorrectly constructed path, so the first step is to look up where api-stubs-timestamp is defined.

find . -name "*.mk" | xargs egrep -n "api-stubs-timestamp"

Got all files containing api-stubs-timestamp, but no one directly defines the target. One of hints is the target might be dynamically generated and related rule droiddoc.  check the file dorddoc.mk, and found

full_target:=$(call doc-timestamp-for,$(LOCAL_MODULE))

Check doc-timestamp-for in definitions.mk, 

define doc-timestamp-for 
$(OUT_DOCS)/$(strip $(1))-timestamp 
endef

Now, we know where is the target come from:  when we specify LOCAL_MODULE as api-stubs, and include $(BUILD_DRODDOC), we make target ..../api-stubs-timestamp.

Search all .mk file for api-stubs MODULE, or check frameworks/base/Android.mk first as the error message shows the target is related to frameworks/base.

Yes, api-stubs MODULE is defined in frameworks/base/Android.mk

Second, how the wrong path frameworks/base//Volumes/Opensource/android/aosp/ frameworks/base is constructed.

Add $(info, LOCAL_SRC_FILES=$(LOCAL_SRC_FILES) ) before $(BUILD_DROIDDOC), in frameworks/base/Android.mk, then build again, the wrong path shows up.

Create a simple Android.mk and track variable LOCAL_SRC_FILES. It leads to find-subdir-files expendable variable in definitions.mk

define find-subdir-files
$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find -L $(1)))
endef

find-subdir-files is supposed to expand as the the result of find command, which are all .java files in this case, but it also includes the LOCAL_PATH, the result of cd command, in my build.

Redirecting the output of cd command to /dev/null can be a workaround for this issue. But it's absolutely not the root reason, because the build script without any modification works anywhere else.

Finally, The root reason

Check cd command in shell: open another terminal window on Mac, and cd to a subdirectory of current location. It has an output.

Compare with Linux, cd command has no output in my Linux box, so the difference comes from the bash installed in my Mac.

Check bash version, the one running on the Mac is 3.2.53; it's 4.2.24 on the Linux box. Is it possible that Mac bash doesn't support Android build?  Ask Google, no one mentioned the Android build needs a specific bash version.

Check bash environment variable which could be specific in my environment, especially the ones which could be related to cd commands, then it comes CDPATH.

Remove CDPATH, and check cd in terminal window on the Mac. There is NO output anymore.

Build Android again. It works!!

Mac: Replace optical bay with OWC data doubler for 2nd HD

It should be a half hour work, but it took me much much much longer because of a stripped screw, which caused the optical bay cannot be taken out. Tried many ways, and finally got the screw out by soldering a small and cheap flat-blade screwdriver to it. A video can be found in youtube.
  • Be very careful not to spatter solder to the Mac logical board. It's better to cover it with something
  • Use a larger and sharp flat blade screwdriver to clean the surface of the stripped screw
  • If it doesn't work for the first time, clean the surface and try again. 

Setup Intel NUC as personal NAS - Debian with btrfs

Debian Setup

  • Selected Debian Testing among Debian Stable, Debian Testing, Mint LMDE.
  • Installed Debian to ext4 partition.
  • After installation, found wireless didn’t work.
    • dmesg | grep eth1  got nothing.
    • checked NUC wireless card, it's Intel dual band wireless 7260
    • then found there was no library for 7260, so apt-cache search 7260 and got firmware-iwlwifi
    • apt-get install firmware-iwlwifi.
    Wireless worked well.

Repartition with cfdisk


Original Debian was installed to an ext4 partition(25G). I decided change to btrfs because of easy snapshot. I can do this by reinstalling everything, but I did it by transferring from my existing installation. So I kept the original ext4 root partition untouched and did repartition as the following
  • Spare space 1G in HD beginning. If Grub stage1 is larger than mbr, it can take some space in the very beginning of the disk. So, we start partition after 1 g from the beginning.
  • 35 G for root as /dev/sda1.
  • 16 G for swap as primary partition and next to /dev/sda1
  • 600 G data partition as first logical partition /dev/sda5.

Configure btrfs for system.

  • My frist idea was to have two btrfs sub volumes, one as /boot, another as /, but I gave up the idea. I only need root (/), so I only have one snapshot for the whole system.
  • I created a sub volume called @rootfs, using @ to distinguish btrfs sub volume from ordinary directory name. ( I didn’t follow Ubuntu btrfs to name the root btrfs as @ ).

Transfer old installation to btrfs volume

  • mount my new btrfs partition as /mnt/btrfs_system
  • mount —bind / /mnt/rawRoot
  • Copy all files to new root
    • cd /mnt/rawRoot
    • tar -cvpf - . | ( cd /mnt/btrfs_system; tar -xpf - )

Configure Grub for new system


After I changed partition schema, Grub cannot boot to either my new system or old system. It entered to rescue mode, as Grub still try to find stage2 in old place, I had to tell Grub the new location of stage2

set prefix=(hd0,msdos1)/@rootfs/boot/grub  # No need to escape @ in Grub. And Grub treats sub volume just like a directory.
set boot=(hd0,msdos1) 
insmod normal  # Grub will try to find module from (hd0,msdos1)/@rootfs/boot/grub/i386. Report errors if it cannot find. 
normal # Continue run Grub Then Grub get to the stage2, 
Then, I got Grub menu. Select one item and Press E. I can see the configuration for stage2 ( ../grub/grub.cfg) still had wrong references to old system, So I have to change grub root and Linux ROOT partition passed to linux kernel.

After that, boot the system.

then, Run update-grub to regenerate /boot/grub/grub.cfg, it overwrites my modification with correct references. and Grub stage2 is correctly configured.

then, run grub-install /dev/sda to replace the old Grub stage1 with the new stage1 which contains the new location for stage2. If there is no unused space in the beginning of the HD, this step returns an error message.

After all changes, reboot the system, and delete old ext4 partition.

Setup Intel NUC as personal NAS - HDD password issue.

Hardware configuration for NUC

  • Intel NUC BOXDN2820FYKH0
  • Crucial CT8G3S160BM 8G
  • WD WD10JFCX Red 1TB ( The NUC will be used as storage mainly )
  • nGear HDMI-DVI/D-25-M/M HDMI to DVI-D Cable ( for my DVI monitor ).

Intel NUC HD password protection is NOT compatible with WD Red


The NAS will be the home of all my data, so it should be a safe place. There are basically two options for data protection.
  • Hardware encryption: Buy a SED drive to protect all data.
  • Software encryption: Use encrypted volume. If my CPU support AES-NI, it will significantly reduce the impact to performance.
SED driver is too expensive and my DN2820 has no support to AES-NI, so my first solution is
  • Use BIOS HD password to protect system (take the risk if a bad guy get my HD and read plates directly); use software encryption to protect my confidential data. It should be a good balance between security and cost.
I learned a little the mechanism about ACCESS control on ATA level. It should be an enhanced ATA feature called ATA security mode feature set. I run hdparm on my WD Red to make sure if it support security mode password protection. It was shown as supported but not enabled.

So, I entered the NUC BIOS and finished the settings for HD master and user password. Then, I turned off the NUC and reboot it again. The NUC did ask me password to boot the system, but neither of master password or user password worked.

I was very sure I used the right passwords. It's most likely a compatibility problem between Intel NUC virtual BIOS and WD Red. And I proved it.

I downloaded a great HD utility called HDAT2, made a DOS boot, run HDAT2, then I unlocked my HDD, then totally removed password protection. The NUC never asked me HD password again. Due to this issue, I had to give up HD password protection and only use encrypted volume to protect my NAS.

JavaScript: Data type conversion by itself

Open the Chrome JavaScript console, and try the following code.

  0 == false;    // true
  0 == ' ';      // true
  0 + 0 == false + ' '; // ???

  0 == ' '      // true
  0 == '0'      // true
  0 + 0 == ' ' + '0'  // ???

  false + '' == 'false' //???
  false == 'false';     //???

  false + '0' == false + 0; // ???

  undefined == null; //???
  undefined === null; //???
  undefined == null + null //???