Merge "Add new raw image sensor HAL pixel format."
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 85187de..83c6de9 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -131,7 +131,9 @@
     info.serial_number[0] = 0;
     if (dev->iSerialNumber) {
         struct usbdevfs_ctrltransfer  ctrl;
-        __u16 buffer[128];
+        // Keep it short enough because some bootloaders are borked if the URB len is > 255
+        // 128 is too big by 1.
+        __u16 buffer[127];
         int result;
 
         memset(buffer, 0, sizeof(buffer));
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index bd16240..d25e58f 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -30,7 +30,8 @@
                           char *dns1,
                           char *dns2,
                           char *server,
-                          uint32_t  *lease);
+                          uint32_t *lease,
+                          char *vendorInfo);
 extern int dhcp_stop(const char *ifname);
 extern int dhcp_release_lease(const char *ifname);
 extern char *dhcp_get_errmsg();
diff --git a/include/sync/sync.h b/include/sync/sync.h
new file mode 100644
index 0000000..6aa5f2d
--- /dev/null
+++ b/include/sync/sync.h
@@ -0,0 +1,45 @@
+/*
+ *  sync.h
+ *
+ *   Copyright 2012 Google, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef __SYS_CORE_SYNC_H
+#define __SYS_CORE_SYNC_H
+
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
+
+__BEGIN_DECLS
+
+/* timeout in msecs */
+int sync_wait(int fd, unsigned int timeout);
+int sync_merge(const char *name, int fd1, int fd2);
+struct sync_fence_info_data *sync_fence_info(int fd);
+struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
+                                  struct sync_pt_info *itr);
+void sync_fence_info_free(struct sync_fence_info_data *info);
+
+/* sw_sync is mainly inteded for testing and should not be complied into
+ * production kernels
+ */
+
+int sw_sync_timeline_create(void);
+int sw_sync_timeline_inc(int fd, unsigned count);
+int sw_sync_fence_create(int fd, const char *name, unsigned value);
+
+__END_DECLS
+
+#endif /* __SYS_CORE_SYNC_H */
diff --git a/include/system/audio.h b/include/system/audio.h
index 4cadb67..382fc36 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -341,6 +341,28 @@
     AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
 } audio_devices_t;
 
+/* the audio output flags serve two purposes:
+ * - when an AudioTrack is created they indicate a "wish" to be connected to an
+ * output stream with attributes corresponding to the specified flags
+ * - when present in an output profile descriptor listed for a particular audio
+ * hardware module, they indicate that an output stream can be opened that
+ * supports the attributes indicated by the flags.
+ * the audio policy manager will try to match the flags in the request
+ * (when getOuput() is called) to an available output stream.
+ */
+typedef enum {
+    AUDIO_OUTPUT_FLAG_NONE = 0x0,    // no attributes
+    AUDIO_OUTPUT_FLAG_DIRECT = 0x1,  // this output directly connects a track
+                                     // to one output stream: no software mixer
+    AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of
+                                     // the device. It is unique and must be
+                                     // present. It is opened by default and
+                                     // receives routing, audio mode and volume
+                                     // controls related to voice calls.
+    AUDIO_OUTPUT_FLAG_FAST = 0x4,    // output supports "fast tracks",
+                                     // defined elsewhere
+} audio_output_flags_t;
+
 static inline bool audio_is_output_device(audio_devices_t device)
 {
     if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h
index 641b177..57f7110 100644
--- a/include/system/audio_policy.h
+++ b/include/system/audio_policy.h
@@ -30,26 +30,6 @@
  * frameworks/base/include/media/AudioSystem.h
  */
 
-/* the audio output flags serve two purposes:
- * - when an AudioTrack is created they indicate a "wish" to be connected to an output stream with
- * attributes corresponding to the specified flags
- * - when present in an output profile descriptor listed for a particular audio hardware module,
- * they indicate that an output stream can be opened that supports the attributes indicated by
- * the flags.
- * the audio policy manager will try to match the flags in the request (when getOuput() is called)
- * to an available output stream.
- */
-typedef enum {
-    AUDIO_POLICY_OUTPUT_FLAG_NONE = 0x0,    // no attributes
-    AUDIO_POLICY_OUTPUT_FLAG_DIRECT = 0x1,  // this output directly connects a track to one output
-                                            // stream (no software mixer)
-    AUDIO_POLICY_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of the device.
-                                            // it is unique and must be present. it is opened by
-                                            // default and receives routing, audio mode and
-                                            // volume controls related to voice calls.
-    AUDIO_POLICY_OUTPUT_FLAG_FAST = 0x4,    // output supports "fast tracks", defined elsewhere
-} audio_policy_output_flags_t;
-
 /* device categories used for audio_policy->set_force_use() */
 typedef enum {
     AUDIO_POLICY_FORCE_NONE,
diff --git a/init/init.c b/init/init.c
index 483544a..4f57144 100755
--- a/init/init.c
+++ b/init/init.c
@@ -648,7 +648,6 @@
         { "ro.boot.serialno", "ro.serialno", "", },
         { "ro.boot.mode", "ro.bootmode", "unknown", },
         { "ro.boot.baseband", "ro.baseband", "unknown", },
-        { "ro.boot.carrier", "ro.carrier", "unknown", },
         { "ro.boot.bootloader", "ro.bootloader", "unknown", },
     };
 
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index d18931b..398d9c4 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -70,7 +70,8 @@
                      char *dns1,
                      char *dns2,
                      char *server,
-                     uint32_t  *lease)
+                     uint32_t *lease,
+                     char *vendorInfo)
 {
     char prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX];
@@ -122,6 +123,10 @@
     if (property_get(prop_name, prop_value, NULL)) {
         *lease = atol(prop_value);
     }
+
+    snprintf(prop_name, sizeof(prop_name), "%s.%s.vendorInfo", DHCP_PROP_NAME_PREFIX, interface);
+    property_get(prop_name, vendorInfo, NULL);
+
     return 0;
 }
 
@@ -158,7 +163,8 @@
                     char *dns1,
                     char *dns2,
                     char *server,
-                    uint32_t  *lease)
+                    uint32_t *lease,
+                    char *vendorInfo)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -207,8 +213,8 @@
     }
     if (strcmp(prop_value, "ok") == 0) {
         char dns_prop_name[PROPERTY_KEY_MAX];
-        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease)
-                == -1) {
+        if (fill_ip_info(interface, ipaddr, gateway, prefixLength,
+                dns1, dns2, server, lease, vendorInfo) == -1) {
             return -1;
         }
 
@@ -305,7 +311,8 @@
                     in_addr_t *dns1,
                     in_addr_t *dns2,
                     in_addr_t *server,
-                    uint32_t  *lease)
+                    uint32_t *lease,
+                    char *vendorInfo)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -341,7 +348,8 @@
         return -1;
     }
     if (strcmp(prop_value, "ok") == 0) {
-        fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease);
+        fill_ip_info(interface, ipaddr, gateway, prefixLength,
+                dns1, dns2, server, lease, vendorInfo);
         return 0;
     } else {
         snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
diff --git a/libsync/Android.mk b/libsync/Android.mk
new file mode 100644
index 0000000..73de069
--- /dev/null
+++ b/libsync/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := sync.c
+LOCAL_MODULE := libsync
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := liblog
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := sync.c sync_test.c
+LOCAL_MODULE := sync_test
+LOCAL_MODULE_TAGS := optional tests
+LOCAL_SHARED_LIBRARIES := liblog
+include $(BUILD_EXECUTABLE)
diff --git a/libsync/sync.c b/libsync/sync.c
new file mode 100644
index 0000000..311da14
--- /dev/null
+++ b/libsync/sync.c
@@ -0,0 +1,115 @@
+/*
+ *  sync.c
+ *
+ *   Copyright 2012 Google, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <sync/sync.h>
+
+int sync_wait(int fd, unsigned int timeout)
+{
+    __u32 to = timeout;
+
+    return ioctl(fd, SYNC_IOC_WAIT, &to);
+}
+
+int sync_merge(const char *name, int fd1, int fd2)
+{
+    struct sync_merge_data data;
+    int err;
+
+    data.fd2 = fd2;
+    strlcpy(data.name, name, sizeof(data.name));
+
+    err = ioctl(fd1, SYNC_IOC_MERGE, &data);
+    if (err < 0)
+        return err;
+
+    return data.fence;
+}
+
+struct sync_fence_info_data *sync_fence_info(int fd)
+{
+    struct sync_fence_info_data *info;
+    int err;
+
+    info = malloc(4096);
+    if (info == NULL)
+        return NULL;
+
+    info->len = 4096;
+    err = ioctl(fd, SYNC_IOC_FENCE_INFO, info);
+    if (err < 0) {
+        free(info);
+        return NULL;
+    }
+
+    return info;
+}
+
+struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
+                                  struct sync_pt_info *itr)
+{
+    if (itr == NULL)
+        itr = (struct sync_pt_info *) info->pt_info;
+    else
+        itr = (struct sync_pt_info *) ((__u8 *)itr + itr->len);
+
+    if ((__u8 *)itr - (__u8 *)info >= (int)info->len)
+        return NULL;
+
+    return itr;
+}
+
+void sync_fence_info_free(struct sync_fence_info_data *info)
+{
+    free(info);
+}
+
+
+int sw_sync_timeline_create(void)
+{
+    return open("/dev/sw_sync", O_RDWR);
+}
+
+int sw_sync_timeline_inc(int fd, unsigned count)
+{
+    __u32 arg = count;
+
+    return ioctl(fd, SW_SYNC_IOC_INC, &arg);
+}
+
+int sw_sync_fence_create(int fd, const char *name, unsigned value)
+{
+    struct sw_sync_create_fence_data data;
+    int err;
+
+    data.value = value;
+    strlcpy(data.name, name, sizeof(data.name));
+
+    err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
+    if (err < 0)
+        return err;
+
+    return data.fence;
+}
diff --git a/libsync/sync_test.c b/libsync/sync_test.c
new file mode 100644
index 0000000..a75f671
--- /dev/null
+++ b/libsync/sync_test.c
@@ -0,0 +1,146 @@
+/*
+ *  sync_test.c
+ *
+ *   Copyright 2012 Google, Inc
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sync/sync.h>
+
+pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct sync_thread_data {
+    int thread_no;
+    int fd[2];
+};
+
+void *sync_thread(void *data)
+{
+    struct sync_thread_data *sync_data = data;
+    struct sync_fence_info_data *info;
+    int err;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+        err = sync_wait(sync_data->fd[i], 10000);
+
+        pthread_mutex_lock(&printf_mutex);
+        if (err < 0) {
+            printf("thread %d wait %d failed: %s\n", sync_data->thread_no,
+                   i, strerror(errno));
+        } else {
+            printf("thread %d wait %d done\n", sync_data->thread_no, i);
+        }
+        info = sync_fence_info(sync_data->fd[i]);
+        if (info) {
+            struct sync_pt_info *pt_info = NULL;
+            printf("  fence %s %d\n", info->name, info->status);
+
+            while ((pt_info = sync_pt_info(info, pt_info))) {
+                int ts_sec = pt_info->timestamp_ns / 1000000000LL;
+                int ts_usec = (pt_info->timestamp_ns % 1000000000LL) / 1000LL;
+                printf("    pt %s %s %d %d.%06d", pt_info->obj_name,
+                       pt_info->driver_name, pt_info->status,
+                       ts_sec, ts_usec);
+                if (!strcmp(pt_info->driver_name, "sw_sync"))
+                    printf(" val=%d\n", *(uint32_t *)pt_info->driver_data);
+                else
+                    printf("\n");
+            }
+            sync_fence_info_free(info);
+        }
+        pthread_mutex_unlock(&printf_mutex);
+    }
+
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    struct sync_thread_data sync_data[4];
+    pthread_t threads[4];
+    int sync_timeline_fd;
+    int i, j;
+    char str[256];
+
+    sync_timeline_fd = sw_sync_timeline_create();
+    if (sync_timeline_fd < 0) {
+        perror("can't create sw_sync_timeline:");
+        return 1;
+    }
+
+    for (i = 0; i < 3; i++) {
+        sync_data[i].thread_no = i;
+
+        for (j = 0; j < 2; j++) {
+            unsigned val = i + j * 3 + 1;
+            sprintf(str, "test_fence%d-%d", i, j);
+            int fd = sw_sync_fence_create(sync_timeline_fd, str, val);
+            if (fd < 0) {
+                printf("can't create sync pt %d: %s", val, strerror(errno));
+                return 1;
+            }
+            sync_data[i].fd[j] = fd;
+            printf("sync_data[%d].fd[%d] = %d;\n", i, j, fd);
+
+        }
+    }
+
+    sync_data[3].thread_no = 3;
+    for (j = 0; j < 2; j++) {
+        sprintf(str, "merged_fence%d", j);
+        sync_data[3].fd[j] = sync_merge(str, sync_data[0].fd[j], sync_data[1].fd[j]);
+        if (sync_data[3].fd[j] < 0) {
+            printf("can't merge sync pts %d and %d: %s\n",
+                   sync_data[0].fd[j], sync_data[1].fd[j], strerror(errno));
+            return 1;
+        }
+    }
+
+    for (i = 0; i < 4; i++)
+        pthread_create(&threads[i], NULL, sync_thread, &sync_data[i]);
+
+
+    for (i = 0; i < 3; i++) {
+        int err;
+        printf("press enter to inc to %d\n", i+1);
+        fgets(str, sizeof(str), stdin);
+        err = sw_sync_timeline_inc(sync_timeline_fd, 1);
+        if (err < 0) {
+            perror("can't increment sync obj:");
+            return 1;
+        }
+    }
+
+    printf("press enter to close sync_timeline\n");
+    fgets(str, sizeof(str), stdin);
+
+    close(sync_timeline_fd);
+
+    printf("press enter to end test\n");
+    fgets(str, sizeof(str), stdin);
+
+    for (i = 0; i < 3; i++) {
+        void *val;
+        pthread_join(threads[i], &val);
+    }
+
+    return 0;
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 1a9e06f..e62c3ea 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -50,6 +50,8 @@
 ALL_PREBUILT += $(file)
 $(INSTALLED_RAMDISK_TARGET): $(file)
 
+# init.usb.rc is handled by build/target/product/core.rc
+
 # Just like /system/etc/init.goldfish.sh, the /init.godlfish.rc is here
 # to allow -user builds to properly run the dex pre-optimization pass in
 # the emulator.
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 90739c0..8f93b49 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -5,6 +5,7 @@
 #
 
 import /init.${ro.hardware}.rc
+import /init.usb.rc
 
 on early-init
     # Set init and its forked children's oom_adj.
@@ -201,11 +202,6 @@
     # Set indication (checked by vold) that we have finished this action
     #setprop vold.post_fs_data_done 1
 
-    chown system system /sys/class/android_usb/android0/f_mass_storage/lun/file
-    chmod 0660 /sys/class/android_usb/android0/f_mass_storage/lun/file
-    chown system system /sys/class/android_usb/android0/f_rndis/ethaddr
-    chmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddr
-
 on boot
 # basic network init
     ifup lo
@@ -325,49 +321,6 @@
     class_reset late_start
     class_reset main
 
-# Used to disable USB when switching states
-on property:sys.usb.config=none
-    stop adbd
-    write /sys/class/android_usb/android0/enable 0
-    write /sys/class/android_usb/android0/bDeviceClass 0
-    setprop sys.usb.state ${sys.usb.config}
-
-# adb only USB configuration
-# This should only be used during device bringup
-# and as a fallback if the USB manager fails to set a standard configuration
-on property:sys.usb.config=adb
-    write /sys/class/android_usb/android0/enable 0
-    write /sys/class/android_usb/android0/idVendor 18d1
-    write /sys/class/android_usb/android0/idProduct D002
-    write /sys/class/android_usb/android0/functions ${sys.usb.config}
-    write /sys/class/android_usb/android0/enable 1
-    start adbd
-    setprop sys.usb.state ${sys.usb.config}
-
-# USB accessory configuration
-on property:sys.usb.config=accessory
-    write /sys/class/android_usb/android0/enable 0
-    write /sys/class/android_usb/android0/idVendor 18d1
-    write /sys/class/android_usb/android0/idProduct 2d00
-    write /sys/class/android_usb/android0/functions ${sys.usb.config}
-    write /sys/class/android_usb/android0/enable 1
-    setprop sys.usb.state ${sys.usb.config}
-
-# USB accessory configuration, with adb
-on property:sys.usb.config=accessory,adb
-    write /sys/class/android_usb/android0/enable 0
-    write /sys/class/android_usb/android0/idVendor 18d1
-    write /sys/class/android_usb/android0/idProduct 2d01
-    write /sys/class/android_usb/android0/functions ${sys.usb.config}
-    write /sys/class/android_usb/android0/enable 1
-    start adbd
-    setprop sys.usb.state ${sys.usb.config}
-
-# Used to set USB configuration at boot and to switch the configuration
-# when changing the default configuration
-on property:persist.sys.usb.config=*
-    setprop sys.usb.config ${persist.sys.usb.config}
-
 ## Daemon processes to be run by init.
 ##
 service ueventd /sbin/ueventd
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
new file mode 100644
index 0000000..15467cc
--- /dev/null
+++ b/rootdir/init.usb.rc
@@ -0,0 +1,91 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# USB configuration common for all android devices
+#
+
+on post-fs-data
+    chown system system /sys/class/android_usb/android0/f_mass_storage/lun/file
+    chmod 0660 /sys/class/android_usb/android0/f_mass_storage/lun/file
+    chown system system /sys/class/android_usb/android0/f_rndis/ethaddr
+    chmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddr
+
+# Used to disable USB when switching states
+on property:sys.usb.config=none
+    stop adbd
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/bDeviceClass 0
+    setprop sys.usb.state ${sys.usb.config}
+
+# adb only USB configuration
+# This should only be used during device bringup
+# and as a fallback if the USB manager fails to set a standard configuration
+on property:sys.usb.config=adb
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct D002
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    start adbd
+    setprop sys.usb.state ${sys.usb.config}
+
+# USB accessory configuration
+on property:sys.usb.config=accessory
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d00
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    setprop sys.usb.state ${sys.usb.config}
+
+# USB accessory configuration, with adb
+on property:sys.usb.config=accessory,adb
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d01
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    start adbd
+    setprop sys.usb.state ${sys.usb.config}
+
+# audio accessory configuration
+on property:sys.usb.config=audio_source
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d02
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    setprop sys.usb.state ${sys.usb.config}
+
+# audio accessory configuration, with adb
+on property:sys.usb.config=audio_source,adb
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d03
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    start adbd
+    setprop sys.usb.state ${sys.usb.config}
+
+# USB and audio accessory configuration
+on property:sys.usb.config=accessory,audio_source
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d04
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    setprop sys.usb.state ${sys.usb.config}
+
+# USB and audio accessory configuration, with adb
+on property:sys.usb.config=accessory,audio_source,adb
+    write /sys/class/android_usb/android0/enable 0
+    write /sys/class/android_usb/android0/idVendor 18d1
+    write /sys/class/android_usb/android0/idProduct 2d05
+    write /sys/class/android_usb/android0/functions ${sys.usb.config}
+    write /sys/class/android_usb/android0/enable 1
+    start adbd
+    setprop sys.usb.state ${sys.usb.config}
+
+# Used to set USB configuration at boot and to switch the configuration
+# when changing the default configuration
+on property:persist.sys.usb.config=*
+    setprop sys.usb.config ${persist.sys.usb.config}