Brillo - Exploring BDK code

     kconfig, fconfig, sensor, sepolicy, wifi_driver_hal
     examples (dbus, lights, service)
     .mk & .sh setup files

bdk/device/generic/goldfish/: qemu peripherals (audio, camera, fingerprint, lights, sensors, vibrator)

bdk/device/generic/mini_emulator_ALL and generic/x86_64 (installed HW): .mk files

bdk/device/intel/edison/flash_tools/ brillo-flashall-edison.*


     daemons, dbus, glib, http, minijail, and individual utils/support files?

bdk/external/libbrillo/policy/: device_policy, libpolicy

class LedFlasherHandler {
  void Register(weave::Device* device) {
    device->AddCommandDefinitionsFromJson(R"({      "_ledflasher": {         "_set":{           "parameters": {             "_led": {"minimum": 1, "maximum": 3},             "_on": "boolean"           }         },         "_toggle":{           "parameters": {             "_led": {"minimum": 1, "maximum": 3}           }        }      }    })");
"_ledflasher._toggle", ...);
"_ledflasher._set", ...);
void OnFlasherSetCommand(const std::weak_ptr<weave::Command>& command) {
    UpdateLedState() ==> device_->SetStateProperty("_ledflasher._leds", list, nullptr);

int main(int argc, char** argv) {
  Daemon daemon{opts};
  LedFlasherHandler handler;
  return 0;
Above appears to be implementation of

bdk/external/libweave/examples/daemon/README: "Acquire Registration Ticket"
Google Developers - OAuth 2.0 Playground
Obtain URL to initialize the playground with the current configuration (includes OAuth credentials and OAuth tokens in the link):

     commands, notification, privet, states StartPrivet, GetGcdState, AddCommandDefinitions, AddCommand, SetStateProperty, .. Load(), Config::Transaction::LoadState()

bdk/external/libweave/third_party/: chromium, modp_b64

bdk/external/: dbus, iptables, jpeg, lib*, rootdev, selinux, toybox, wpa_supplicant_8

bdk/frameworks/av/: camera, drm, media, radio, services, sound_trigger

bdk/frameworks/native/: cmds
bdk/frameworks/native/data/etc/: android.hardware.*.xml
             <feature name="android.hardware.* " />
bdk/frameworks/native/include/: android, diskusage, gui, input, media, powermanager, private, ui
bdk/frameworks/native/libs/: binder, diskusage, gui, input, ui
bdk/frameworks/native/services/: battery, powermanager, sensor

bdk/frameworks/rs/: Render Script (?)
bdk/frameworks/wilhelm/: OpenMAXAL, OpenSLES

     bsp/intel/peripheral/: audio, bluetooth, libmraa, libupm, light, sensors, wifi
     bsp/intel/soc/edison/: bootctrl, sepolicy
     libhardware/modules/: audio, camera, input, nfc, power, radio, sensors, soundtrigger, vibrator

bdk/libnativehelper/: JNI

     system/bin - Linux?
     system/etc/os-release.d/bdk_version & product_version
     boot.img, kernel, ramdisk.img, system.img, userdata.img


     common/brillo_gpios/src/gpio_playground/gpio_playground.cpp: Export "/sys/class/gpio" & file stream
     common/brillo_leds/src/brillo_led_tool/brillo_led_tool.cpp: Toggle "/sys/class/leds/led*/brightness"
     common/sensors_example: Accelerometer and other sensors hw_get_module(SENSORS_HARDWARE_MODULE_ID?

     example-ledflasher/config/brillo/product_id: developer-boards:ledflasher
         Used by the backends to route metrics/crash reports to the right customer.

  "_ledflasher": {
    "_set": {
      "parameters": {
        "_led": {"minimum": 1, "maximum": 4},
        "_on": "boolean"      }
    "_toggle": {
      "parameters": {
        "_led": {"minimum": 1, "maximum": 4}
    "_animate": {
      "parameters": {
        "_duration": {"minimum": 0.1, "maximum": 100.0},
        "_type": ["none", "marquee_left", "marquee_right", "blink"]
  "_ledflasher": {
    "_status": {
      "enum": ["idle", "animating"],
      "default": "idle"    },
    "_leds": {"items": "boolean"}
     These two look identical (except additional "animation" in ledflasher.cpp):
     But I couldn't decide whether they are interacting with same device & using identical mode of interaction.

    <node name="/com/android/LEDService/Service"
      <interface name="">
        <method name="SetLED">

  "service_name": "",
  "object_manager": {
    "name": "",
    "object_path": "/com/android/LEDService"  }

Brillo - Building from Source Code

Building Brillo from Source Code:

Need 40GB VM diskspace (ubuntu, tools, code, build), 2GB swap, 2GB RAM.
Took 4+hrs. More RAM should make it much much faster.

Follow Android build/environment steps:
# Update Ubuntu 10.04
sudo apt-get install git-core gnupg flex bison gperf build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
libgl1-mesa-dev libxml2-utils xsltproc unzip
# for lunch
sudo apt-get install python-lunch
# for java and javac
sudo apt-get install openjdk-7-jre-headless
sudo apt-get install openjdk-7-jdk

ccache is a compiler cache for C and C++ that can help make builds faster. In the root of the source tree, do the following:
export USE_CCACHE=1
export CCACHE_DIR=$HOME/.ccache # /<path_of_your_choice>/.ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G
# The suggested cache size is 50-100G.
# watch ccache being used by doing the following:
watch -n1 -d prebuilts/misc/linux-x86/ccache/ccache -s

error: cannot exceed 91 bytes:

Brillo/brilloemulator_x86_64/brilloemulator_x86_64:6.0.60/MASTER/shreekant02040032:eng/test-keys (96)
To avoid this error, use suitable shorter user login name such that fingerprint doesn't exceed 91 bytes.

For instance, above becomes 89 char fingerprint for user "sk":

Building From Official (Stable) Release:

# Ref
tar -xzf bdk-latest.tar.gz
{BDK_PATH}/tools/bdk/brunch/brunch bsp list
{BDK_PATH}/tools/bdk/brunch/brunch bsp download <bsp-name>

bdk$ source build/ && lunch
selected 9. brilloemulator_x86_64-eng

bdk$ make -j
TARGET_DEVICE brilloemulator_x86_64 (

? /home/sk/brillo/bdk/hardware/bsp/kernel/common/android-3.18
? /home/sk/brillo/bdk/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin

[100% 10445/10445] Install system fs image:
out/target/product/brilloemulator_x86_64/system.img+out/target/product/brilloemulator_x86_64/recovery.img maxsize=802897920 blocksize=2112 total=793860096 reserve=8110080

# Brillo emulator - Runtime setup

export PATH=\

export ANDROID_BUILD_TOP=/home/sk/brillo/bdk

# Start brillo emulator

Building from Latest Development Branch: (Just for info; Not actually tried/tested)

# Ref
mkdir brillo-master
cd brillo-master
# for repo
sudo apt-get install phablet-tools
repo init -u -b master
many more commands & useful fixes in Ref.

Brillo - Basics

Brillo is an IoT Platform Eco-system involves:

  • Embedded OS running on a device,
  • Client/interface App running on Android Phone, and
  • Cloud service to coordinate between devices, owners & users.

Brillo: Embedded OS based on Android

  • BSP for specific board
  • Supports ARM, Intel, MIPS architecture)
  • Smallest configuration 32MB of RAM, and 128MB of storage
  • Supports Wi-Fi and Bluetooth Low Energy
  • Runs on battery-powered devices

Brillo Core platform services:

  • Weave (helps devices to securely connect to the network)
  • Metrics (collect usage data from devices based on the user permission)
  • Console to view & analyze data,
  • Collect crash report & debug data from field
  • Over-the-air (OTA) Push updates,
  • Developer kit: build, debug, test device
    • build architecture
    • Runs on Ubuntu 14.04
    • Local Unit test, individual Integration tests, or Own Continuous Build Integration Testing infrastructure.
    • Andoid Debug Bridge (adb) over Ethernet or USB (without any special equipment)

Weave library maintained in Brillo OS:

  • Provides:
    • Setup, Interaction, and communication with wide range of connected devices.
    • Ability to communicate with device directly or through Cloud servicess.
    • Common Language for app or services to use across all of user devices. [based on JSON]
  • Protocol:
    • Device Discovery
    • Provisioning
    • Authentication & Interaction implemented across device-side libraries, mobile SDKs and web service that enables remote interactions.
  • Schema: Commands and States that are common for device types
    • customized & extended for a particular product
  • Cloud Service: Remote communication service integrated in Weave.
    • provides aggregated metrics in developer console to analyze all devices.
  • Client app/services on mobile/desktop/web to setup/interact with devices.
    • Secure setup experience common to all devices that works from both Android & iOS devices.
    • Communicate with your and devices made by other developers using same standardized schemas.

Brillo Boards:


  • Intel Edison Board Made for Brillo:
    Intel EDI2ARDUIN.AL.K Dual Core IA-32 @ 500 MHz, 32-bit Intel Atom Processor Z34xx Series @ 100 MHz Board with 70-pin connector Motherboard/CPU Combo ==> "Edison kit for Arduino"
    Flashing Brillo on Edison (plus some links on right)

[Need to obtain access permissions! Apply at]
    Intel Edison and Peripherals
        Edison and Grove (Plus/Gen2 sensors, actuators and shields)
   Grove Software Library for Edison

  • MIPS-based Imagination Creator board for Brillo:
  • ARM-based PICO-i.MX6UL and DWARF board for Brillo:

Switching deprecated attr_accessible to Rails 4+ Strong Parameters with gem 'cancancan'

class User < ActiveRecord::Base
  ##attr_accessible :name, :full_name, :family, :roles_mask, :password
  validates :name, :presence => true,

            :uniqueness => { :case_sensitive => false,
              :message => "is already used! Error: Duplicate Login Name." }
  validates :password, :on => :create, :presence => true
  def roles=(roles) # roles array to bitmask
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum

class UsersController < ApplicationController
  # Use cancan authorization in all methods with support for Rails 4+ Strong Parameters
  load_and_authorize_resource param_method: :user_params
  def update

  def create_multiple
          new_params[:family]         = fields[0].strip
          new_params[:name]           = fields[1].strip
          new_params[:roles]          = fields[3].strip.split(/,/)  # actually sets :roles_mask
          new_params[:password] = new_params[:password_confirmation] = new_params[:name]
          @user ={user: new_params}) ))


    def user_params(custom_params = nil)
      custom_params ||= params
      # roles_mask, password_confirmation and password_digest

      # are not included in the permit list here:
      custom_params.require(:user).permit(:name, :family, :full_name, :valid_upto,
                            :password, roles:[]) # "roles:[]" must be the last param here.
             # See

Android Notes

Using Custom Adapter to save and render fetched data (image) in AsyncTask

    private class FetchMovieListTask extends AsyncTask<String, Void, ArrayList<MovieData>> {
        private ArrayList<MovieData> getMovieList(String jsonString) {
            while (json) {
                MovieData movieData = new MovieData(...);
            return movieList;
        protected ArrayList<MovieData> doInBackground(String... params) {
            return getMovieList(responseStr);
        protected void onPostExecute(ArrayList<MovieData> movieList) {
            for (MovieData movieData : movieList) {
    private class ImageAdapter extends ArrayAdapter<MovieData> {
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView imageView;
            if (convertView == null) {
                imageView = new ImageView(getContext());
                : initialize some attributes
            } else {
                imageView = (ImageView) convertView;
            MovieData movieData = getItem(position);
            // Takes care of downloading & showing it in sync with UI thread, as well as caching images:
            return imageView;

Picasso Image Library

    mAdapter = new ImageAdapter(getActivity(), R.layout.movie_item_image,, initialList);
    // ??? This layout/view doesn't seem to make much difference as even TextView also shows gridview images!! May be that's because of below overridden getView()???
    private class ImageAdapter extends ArrayAdapter<String> {
        public ImageAdapter(Context context, int resource, int textViewResourceId, ArrayList<String> objects) {
            super(context, resource, textViewResourceId, objects);
        public View getView(int position, View convertView, ViewGroup parent) {
            // takes care of downloading & showing it in sync with UI thread, as well as caching images.
            return imageView;

Obtaining Unique PendingIntents for Associated Intents

A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. If you use two Intent objects that are equivalent, then the same PendingIntent is provided for both of them.

For purposes of intent resolution (filtering)/retrieving a PendingIntent, two Intents are considered to be equivalent if their action, data, type, class, and categories are the same. This DOES NOT compare any extra data included in the intents!! See Intent.filterEquals.

So even if extras differ, to obtain Unique PendingIntents (per instance of the target purpose/activity/service/broadcast), either forcefully set unique Data in Intent, or use unique Request code while creating the PendingIntent.

        final Bundle extras = new Bundle();
        extras.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        final Intent settingsActivityIntent = new Intent(context, YmdhmsAppWidgetSettings.class)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // in case activity is started outside of the context of an existing activity
        // IMPORTANT: PendingIntent will be reused even if extras differ between the intents targeted for different instances of AppWidgets.
        // This creates a problem by using latest extras (appWidgetId) for ALL previous and new instances of AppWidgets!!
        // One option is to make Intent's Data unique by using toUri, effectively forcing creation of separate PendingIntents:
        // Or, Another better/cleaner solution is to unique requestCode for creating unique PendingIntents for each AppWidget.
        final PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, // use unique request code to create unique PendingIntents
                settingsActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);


Dynamically Adding Views (based on data/options)

  • Create an empty "place-holder anchor" LinearLayout movie_review_list
  • Dynamically inflate movie_review_link views
  • Instantiate and add into the list
        ArrayList<String[]> mReviews;
        list = (LinearLayout) rootView.findViewById(;
        for ( int i=0; i < movieReviews.size(); i++ ) {
            View vi = inflater.inflate(R.layout.movie_review_link, null);


setTag() & getTag() on Button/Text View (similar to PutExtra for intents)

Attach custom data using setTag() to a Button/Text view for later retrieval onClick: (similar to PutExtra for intents)
            Button readButton = (Button) vi.findViewById(;
            readButton.setTag(movieReviews.get(i)[1]); // Save/attach review uri, which would be used onClick.
              new View.OnClickListener() {
                public void onClick(View v) {
                    String uriString = (String) v.getTag();
                    Log.v(LOG_TAG, "Review url: " + uriString);


Invoking Fragment's methods from Activity

public class MainActivity extends ActionBarActivity {
        // First tag a fragment during committing transaction:
                .add(, new ForecastFragment(), FORECASTFRAGMENT_TAG)

        // When needed, locate the fragment and invoke its method:
        ForecastFragment ff = (ForecastFragment)getSupportFragmentManager().findFragmentByTag(FORECASTFRAGMENT_TAG);


Adding JUnit support in a project

Add Sunshine\app\src\androidTest\java\com\example\shreekant\sunshine\app\
FullTestSuite contains all Java test classes packaged into a suite that JUnit can run.
Thus, additional tests can be added by just adding a java class file.
    public class TestPractice extends AndroidTestCase {

        protected void setUp() throws Exception { super.setUp(); }          // called before each test
        protected void tearDown() throws Exception { super.tearDown(); }    // called after each test

        // A method with prefix "test" is automatically called by Test Manager:
        public void testThatDemonstratesAssertions() throws Throwable {
            // should have at least one assert
            assertEquals("X should be equal", a, c);
To run tests,
Android Studio => Sunshine => app => src => androidTest => java =>
=> Right click -> Run Tests in 'com.example...
      Select the one with Android icon (and not the Gradle icon)

Formatting Strings

    <xliff:g> marks message parts that should not be translated.
    <!-- Date format for displaying day of week and date (i.e. Mon Jun 1) [CHAR LIMIT=20] -->
    <string name="format_full_friendly_date"><xliff:g id="day">%1$s</xliff:g>, <xliff:g id="date">%2$s</xliff:g></string>
    <!-- Format for displaying Temperature and Unicode U+00B0 ° degree sign [CHAR LIMIT=20] -->
    <string name="format_temperature"><xliff:g id="temperature">%1.0f</xliff:g>\u00B0</string>
    return String.format(context.getString(
    Or, a shorter version:
    return context.getString(R.string.format_full_friendly_date,
    return context.getString(R.string.format_temperature, temp);

List Item Selection Color

    <color name="grey">#cccccc</color>
    <color name="sunshine_light_blue">#ff64c2f4</color>
    <color name="red">#ff0000</color>
    <color name="green">#7eff00</color>
    <color name="cyan">#00ffff</color>
    <color name="magenta">#7e00ff</color>
drawable/touch_selector.xml: ## Create empty selector so that reference to "@drawable/touch_selector" doesn't crash on devices prior to Honeycomb API v11.
    <selector xmlns:android="">
        <!-- Here it's a stub for API < v11.  Appropriate method of indicating touch states is defined for
        higher API versions -->
drawable-v11/touch_selector.xml: ## Background attributes/state_activated are NOT SUPPORTED prior to Honeycomb API v11.
    <item android:state_pressed="true"
      android:drawable="@color/grey" />
    <!-- When the view is "activated".  In SINGLE_CHOICE_MODE, it flags the active row
         of a ListView -->
    <item android:state_activated="true"
          android:drawable="@color/sunshine_light_blue" />
drawable-v21/touch_selector.xml: ## Use new "ripple" UI for v21 and above.
    <item android:state_pressed="true">
      <ripple android:color="@color/grey" />
    <!-- When the view is "activated".  In SINGLE_CHOICE_MODE, it flags the active row
         of a ListView -->
    <item android:state_activated="true"
          android:drawable="@color/sunshine_light_blue" />
    <style name="ForecastListStyle">
        <!-- Here it's a stub.  In screens of sufficient width, this style includes modifications
        for two-pane layout -->
values-sw600dp/styles.xml: ## Setting choiceMode to singleChoice enables appropriate type of "activated" touch_selector based on API version.
    <style name="ForecastListStyle">
        <item name="android:choiceMode">singleChoice</item>

List & List Item Layout: ## Finally, use style to distinguish between phone & tablet behavior

Apply API version based appropriate type of background touch selector to represent states of a list item:

In screens of sufficient width, set singleChoice mode to enable "activated" touch_selector:


UX Layouts Redlines (UI textsize / textAppearance)

48dp translates to a physical size of about 9mm (with some variability). This is comfortably in the range of recommended target sizes (7-10mm) for touchscreen objects and ensures that users will be able to reliably and accurately target them with their fingers.

Text Size Scalable Pixels (sp) Scale-independent Pixels
Definitions for current/old phone??
    Text Size Micro     12sp    ????
    Text Size Small     14sp    "?android:textAppearanceSmall"
    Text Size Medium    18sp    "?android:textAppearanceMedium"
    Text Size Large     22sp    "?android:textAppearanceLarge"

A set of six generalized densities:
    ldpi (low) ~120dpi
    mdpi (medium) ~160dpi
    hdpi (high) ~240dpi
    xhdpi (extra-high) ~320dpi
    xxhdpi (extra-extra-high) ~480dpi
    xxxhdpi (extra-extra-extra-high) ~640dpi

Layout Screen Width (layout-swXXXdp): dp - Density-independent Pixels
    320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
    480dp: a tweener tablet like the Streak (480x800 mdpi).
    600dp: a 7” tablet (600x1024 mdpi).
    720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).

Conversion of dp units to screen pixels:
    px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels.

px changes based on dpi (device resulution), pt, dp and sp remain (relatively) constant:
    1 inch = 72pt = 160dp = 160sp

Motoroly Defy+ MB256:
Resolution 480 x 854 pixels (~265 ppi pixel density). Screen 3.7 inch. Body 4.21 x 2.32 x 0.53 inch.
screen resolution / display metrics
    DisplayMetrics{density=1.5, densityDpi=240, width=480, height=854, scaledDensity=1.5, xdpi=265.0435, ydpi=264.5317}
densityDpi 240 => DENSITY_HIGH.
    DENSITY_280     Intermediate density for screens that sit between DENSITY_HIGH (240dpi) and DENSITY_XHIGH (320dpi).


Maintain Position of a List Item after Screen is Rotated

  • In setOnItemClickListener/onItemClick, remember the view and position.
  • onSaveInstanceState, save it to bundle.
  • onCreateView, read it back. (But don't apply it yet, as listview might not have been populated)
  • onLoadFinished, actually set the smoothScrollToPosition for the view

Reuse/Share View in Wide-screen and Landscape modes

layout/fragment_detail.xml: Regular view for (small) phone.
    layout/fragment_detail_wide.xml: Wider view for wider screens (landscape-mode phones & tables)
    values-land/refs.xml, values-sw600dp/refs.xml: Point/link/references to shared view.
        <item name="fragment_detail" type="layout">@layout/fragment_detail_wide</item>


Show a popup message

    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

Chronometer (Stop Watch) as Time Piece (Current Time)

        long elapsedTime = SystemClock.elapsedRealtime();
        Calendar calendar = Calendar.getInstance();
        long currTimeInMilli = (calendar.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000) +
                (calendar.get(Calendar.MINUTE) * 60 * 1000) +
                (calendar.get(Calendar.SECOND) * 1000) +
        // The value set as setBase is *subtracted* from the chronoBase and that time is shown by Chronometer.
        // Thus, setBase(SystemClock.elapsedRealtime()) sets the clock to 00:00.
        // elapsedTime = 3:00                       Clock (currTime)
        //   setBase(elapsedTime) -> 3:00 - 03:00 = 00:00
        //   setBase(01:00)       -> 3:00 - 01:00 = 02:00
        //   setBase(-01:00)      -> 3:00 + 01:00 = 04:00
        //  baseToSet = elapsedTime - currTime
        mViewHolder.chrono.setBase(elapsedTime - currTimeInMilli);

Android Tools - Shell interface

# Install gradle
"C:\Program Files\Android\Android Studio\gradle\gradle-2.2.1"

# Build app
/cygdrive/c/Program\ Files/Android/Android\ Studio/gradle/gradle-2.2.1/bin/gradle assembleDebug

# Run adb to install (copy/overwrite) apk to device
$ /cygdrive/c/Users/sr/AppData/Local/Android/sdk/platform-tools/adb.exe  install -r app/build/outputs/apk/app-debug-unaligned.apk

# Run adb "am start" to launch app
$ /cygdrive/c/Users/sr/AppData/Local/Android/sdk/platform-tools/adb.exe  shell am start -n


Genymotion emulator (works with Virtual Box) loads much faster than default Google/Android virtual device emulators.
Genymotion was installed in C:\Users\shreekant\AppData\Local\Genymobile\

ig4icd32.dll is crashing both in Android Studio and Genymotion.
Intel/HP driver was last updated in 2009. So looks like, there may not be any solution to this issue as stated in here:

BIG TMP images are kept in C:\Users\sr\AppData\Local\Temp\AndroidEmulator\. -- Delete when done.

Android SDK was installed to C:\Users\sr\AppData\Local\Android\sdk