am d239dbb2: am 170bde83: (-s ours) resolved conflicts for merge of 7c327194 to lmp-mr1-ub-dev
* commit 'd239dbb2578ca70cb4cd44b78a0295bdd8af0e36':
libutils: fix overflow in SharedBuffer [DO NOT MERGE]
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index 18289e2..f3db346 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -64,6 +64,14 @@
struct usb_endpoint_descriptor_no_audio sink;
} __attribute__((packed));
+struct ss_func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_ss_ep_comp_descriptor source_comp;
+ struct usb_endpoint_descriptor_no_audio sink;
+ struct usb_ss_ep_comp_descriptor sink_comp;
+} __attribute__((packed));
+
struct desc_v1 {
struct usb_functionfs_descs_head_v1 {
__le32 magic;
@@ -79,7 +87,9 @@
// The rest of the structure depends on the flags in the header.
__le32 fs_count;
__le32 hs_count;
+ __le32 ss_count;
struct func_desc fs_descs, hs_descs;
+ struct ss_func_desc ss_descs;
} __attribute__((packed));
struct func_desc fs_descriptors = {
@@ -136,6 +146,41 @@
},
};
+static struct ss_func_desc ss_descriptors = {
+ .intf = {
+ .bLength = sizeof(ss_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(ss_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .source_comp = {
+ .bLength = sizeof(ss_descriptors.source_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ },
+ .sink = {
+ .bLength = sizeof(ss_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .sink_comp = {
+ .bLength = sizeof(ss_descriptors.sink_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ },
+};
+
#define STR_INTERFACE_ "ADB Interface"
static const struct {
@@ -279,11 +324,14 @@
v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
- v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
+ v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
+ FUNCTIONFS_HAS_SS_DESC;
v2_descriptor.fs_count = 3;
v2_descriptor.hs_count = 3;
+ v2_descriptor.ss_count = 5;
v2_descriptor.fs_descs = fs_descriptors;
v2_descriptor.hs_descs = hs_descriptors;
+ v2_descriptor.ss_descs = ss_descriptors;
if (h->control < 0) { // might have already done this before
D("OPENING %s\n", USB_FFS_ADB_EP0);
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 2d1abbe..60f5398 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -859,6 +859,7 @@
int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
{
_Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE];
+ bool use_state = true;
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
@@ -875,7 +876,10 @@
property_get("ro.boot.veritymode", propbuf, "");
if (*propbuf != '\0') {
- return 0; /* state is kept by the bootloader */
+ if (fs_mgr_load_verity_state(&mode) == -1) {
+ return -1;
+ }
+ use_state = false; /* state is kept by the bootloader */
}
fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
@@ -900,9 +904,11 @@
continue;
}
- if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
- read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
- continue;
+ if (use_state) {
+ if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
+ read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
+ continue;
+ }
}
mount_point = basename(fstab->recs[i].mount_point);
@@ -916,7 +922,7 @@
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
- if (*status == 'C') {
+ if (use_state && *status == 'C') {
if (write_verity_state(fstab->recs[i].verity_loc, offset,
VERITY_MODE_LOGGING) < 0) {
continue;
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 7ea8250..c75ed13 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -181,6 +181,7 @@
props.chargerWirelessOnline = false;
props.batteryStatus = BATTERY_STATUS_UNKNOWN;
props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
+ props.maxChargingCurrent = 0;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -235,6 +236,15 @@
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
+ path.clear();
+ path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+ mChargerNames[i].string());
+ if (access(path.string(), R_OK) == 0) {
+ int maxChargingCurrent = getIntField(path);
+ if (props.maxChargingCurrent < maxChargingCurrent) {
+ props.maxChargingCurrent = maxChargingCurrent;
+ }
+ }
}
}
}
@@ -341,9 +351,9 @@
int v;
char vs[128];
- snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d\n",
+ snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline,
- props.chargerWirelessOnline);
+ props.chargerWirelessOnline, props.maxChargingCurrent);
write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
props.batteryStatus, props.batteryHealth, props.batteryPresent);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 9e5f9ff..8eb5b5b 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -803,9 +803,9 @@
return -1;
}
-int do_load_all_props(int nargs, char **args) {
+int do_load_system_props(int nargs, char **args) {
if (nargs == 1) {
- load_all_props();
+ load_system_props();
return 0;
}
return -1;
@@ -833,18 +833,31 @@
return 0;
}
+static bool is_file_crypto() {
+ char prop_value[PROP_VALUE_MAX] = {0};
+ property_get("ro.crypto.type", prop_value);
+ return strcmp(prop_value, "file") == 0;
+}
+
int do_installkey(int nargs, char **args)
{
if (nargs != 2) {
return -1;
}
-
- char prop_value[PROP_VALUE_MAX] = {0};
- property_get("ro.crypto.type", prop_value);
- if (strcmp(prop_value, "file")) {
+ if (!is_file_crypto()) {
return 0;
}
-
return e4crypt_create_device_key(args[1],
do_installkeys_ensure_dir_exists);
}
+
+int do_setusercryptopolicies(int nargs, char **args)
+{
+ if (nargs != 2) {
+ return -1;
+ }
+ if (!is_file_crypto()) {
+ return 0;
+ }
+ return e4crypt_set_user_crypto_policies(args[1]);
+}
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 666a86e..62e8b10 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -159,7 +159,7 @@
case 'l':
if (!strcmp(s, "oglevel")) return K_loglevel;
if (!strcmp(s, "oad_persist_props")) return K_load_persist_props;
- if (!strcmp(s, "oad_all_props")) return K_load_all_props;
+ if (!strcmp(s, "oad_system_props")) return K_load_system_props;
break;
case 'm':
if (!strcmp(s, "kdir")) return K_mkdir;
@@ -187,6 +187,7 @@
if (!strcmp(s, "etenv")) return K_setenv;
if (!strcmp(s, "etprop")) return K_setprop;
if (!strcmp(s, "etrlimit")) return K_setrlimit;
+ if (!strcmp(s, "etusercryptopolicies")) return K_setusercryptopolicies;
if (!strcmp(s, "ocket")) return K_socket;
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
diff --git a/init/keywords.h b/init/keywords.h
index e637d7d..0910f60 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -22,6 +22,7 @@
int do_rmdir(int nargs, char **args);
int do_setprop(int nargs, char **args);
int do_setrlimit(int nargs, char **args);
+int do_setusercryptopolicies(int nargs, char **args);
int do_start(int nargs, char **args);
int do_stop(int nargs, char **args);
int do_swapon_all(int nargs, char **args);
@@ -34,7 +35,7 @@
int do_chmod(int nargs, char **args);
int do_loglevel(int nargs, char **args);
int do_load_persist_props(int nargs, char **args);
-int do_load_all_props(int nargs, char **args);
+int do_load_system_props(int nargs, char **args);
int do_verity_load_state(int nargs, char **args);
int do_verity_update_state(int nargs, char **args);
int do_wait(int nargs, char **args);
@@ -66,7 +67,7 @@
KEYWORD(installkey, COMMAND, 1, do_installkey)
KEYWORD(ioprio, OPTION, 0, 0)
KEYWORD(keycodes, OPTION, 0, 0)
- KEYWORD(load_all_props, COMMAND, 0, do_load_all_props)
+ KEYWORD(load_system_props, COMMAND, 0, do_load_system_props)
KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props)
KEYWORD(loglevel, COMMAND, 1, do_loglevel)
KEYWORD(mkdir, COMMAND, 1, do_mkdir)
@@ -86,6 +87,7 @@
KEYWORD(setenv, OPTION, 2, 0)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
+ KEYWORD(setusercryptopolicies, COMMAND, 1, do_setusercryptopolicies)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
diff --git a/init/property_service.cpp b/init/property_service.cpp
index c2881ae..52f6b98 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -560,16 +560,10 @@
close(fd);
}
-void load_all_props() {
+void load_system_props() {
load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
-
- load_override_properties();
-
- /* Read persistent properties after all default values have been loaded. */
- load_persistent_properties();
-
load_recovery_id_prop();
}
diff --git a/init/property_service.h b/init/property_service.h
index a27053d..303f251 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -23,7 +23,7 @@
extern void property_init(void);
extern void property_load_boot_defaults(void);
extern void load_persist_props(void);
-extern void load_all_props(void);
+extern void load_system_props(void);
extern void start_property_service(void);
void get_property_workspace(int *fd, int *sz);
extern int __property_get(const char *name, char *value);
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index d584925..823a842 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -72,7 +72,7 @@
return;
}
entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
- times.push_back(entry);
+ times.push_front(entry);
}
client->incRef();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 0f5071b..db3f26c 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -217,19 +217,22 @@
return len;
}
-// If we're using more than 256K of memory for log entries, prune
-// at least 10% of the log entries.
+// Prune at most 10% of the log entries or 256, whichever is less.
//
// mLogElementsLock must be held when this function is called.
void LogBuffer::maybePrune(log_id_t id) {
size_t sizes = stats.sizes(id);
- if (sizes > log_buffer_size(id)) {
- size_t sizeOver90Percent = sizes - ((log_buffer_size(id) * 9) / 10);
+ unsigned long maxSize = log_buffer_size(id);
+ if (sizes > maxSize) {
+ size_t sizeOver = sizes - ((maxSize * 9) / 10);
size_t elements = stats.elements(id);
- unsigned long pruneRows = elements * sizeOver90Percent / sizes;
- elements /= 10;
- if (pruneRows <= elements) {
- pruneRows = elements;
+ size_t minElements = elements / 10;
+ unsigned long pruneRows = elements * sizeOver / sizes;
+ if (pruneRows <= minElements) {
+ pruneRows = minElements;
+ }
+ if (pruneRows > 256) {
+ pruneRows = 256;
}
prune(id, pruneRows);
}
@@ -237,7 +240,12 @@
LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection::iterator it) {
LogBufferElement *e = *it;
+ log_id_t id = e->getLogId();
+ LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
+ if ((f != mLastWorstUid[id].end()) && (it == f->second)) {
+ mLastWorstUid[id].erase(f);
+ }
it = mLogElements.erase(it);
stats.subtract(e);
delete e;
@@ -396,8 +404,17 @@
bool kick = false;
bool leading = true;
+ it = mLogElements.begin();
+ if (worst != (uid_t) -1) {
+ LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(worst);
+ if ((f != mLastWorstUid[id].end())
+ && (f->second != mLogElements.end())) {
+ leading = false;
+ it = f->second;
+ }
+ }
LogBufferElementLast last;
- for(it = mLogElements.begin(); it != mLogElements.end();) {
+ while (it != mLogElements.end()) {
LogBufferElement *e = *it;
if (oldest && (oldest->mStart <= e->getSequence())) {
@@ -447,8 +464,10 @@
continue;
}
+ // unmerged drop message
if (dropped) {
last.add(e);
+ mLastWorstUid[id][e->getUid()] = it;
++it;
continue;
}
@@ -493,6 +512,7 @@
delete e;
} else {
last.add(e);
+ mLastWorstUid[id][e->getUid()] = it;
++it;
}
}
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a13fded..e94598c 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -19,9 +19,10 @@
#include <sys/types.h>
+#include <list>
+
#include <log/log.h>
#include <sysutils/SocketClient.h>
-#include <utils/List.h>
#include <private/android_filesystem_config.h>
@@ -30,7 +31,7 @@
#include "LogStatistics.h"
#include "LogWhiteBlackList.h"
-typedef android::List<LogBufferElement *> LogBufferElementCollection;
+typedef std::list<LogBufferElement *> LogBufferElementCollection;
class LogBuffer {
LogBufferElementCollection mLogElements;
@@ -39,6 +40,11 @@
LogStatistics stats;
PruneList mPrune;
+ // watermark of any worst/chatty uid processing
+ typedef std::unordered_map<uid_t,
+ LogBufferElementCollection::iterator>
+ LogBufferIteratorMap;
+ LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
unsigned long mMaxSize[LOG_ID_MAX];
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 783bce6..39bcdd4 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -20,8 +20,10 @@
#include <pthread.h>
#include <time.h>
#include <sys/types.h>
+
+#include <list>
+
#include <sysutils/SocketClient.h>
-#include <utils/List.h>
#include <log/log.h>
class LogReader;
@@ -107,6 +109,6 @@
static int FilterSecondPass(const LogBufferElement *element, void *me);
};
-typedef android::List<LogTimeEntry *> LastLogTimes;
+typedef std::list<LogTimeEntry *> LastLogTimes;
-#endif
+#endif // _LOGD_LOG_TIMES_H__
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index 277b3ca..16dd6d2 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -50,18 +50,14 @@
}
PruneList::PruneList() : mWorstUidEnabled(true) {
- mNaughty.clear();
- mNice.clear();
}
PruneList::~PruneList() {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {
- delete (*it);
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {
- delete (*it);
it = mNaughty.erase(it);
}
}
@@ -70,11 +66,9 @@
mWorstUidEnabled = true;
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {
- delete (*it);
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {
- delete (*it);
it = mNaughty.erase(it);
}
@@ -142,28 +136,28 @@
// insert sequentially into list
PruneCollection::iterator it = list->begin();
while (it != list->end()) {
- Prune *p = *it;
- int m = uid - p->mUid;
+ Prune &p = *it;
+ int m = uid - p.mUid;
if (m == 0) {
- if (p->mPid == p->pid_all) {
+ if (p.mPid == p.pid_all) {
break;
}
- if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
+ if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
it = list->erase(it);
continue;
}
- m = pid - p->mPid;
+ m = pid - p.mPid;
}
if (m <= 0) {
if (m < 0) {
- list->insert(it, new Prune(uid,pid));
+ list->insert(it, Prune(uid,pid));
}
break;
}
++it;
}
if (it == list->end()) {
- list->push_back(new Prune(uid,pid));
+ list->push_back(Prune(uid,pid));
}
if (!*str) {
break;
@@ -193,7 +187,7 @@
for (it = mNice.begin(); it != mNice.end(); ++it) {
char *a = NULL;
- (*it)->format(&a);
+ (*it).format(&a);
string.appendFormat(fmt, a);
fmt = nice_format;
@@ -205,7 +199,7 @@
fmt = naughty_format + (*fmt != ' ');
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
char *a = NULL;
- (*it)->format(&a);
+ (*it).format(&a);
string.appendFormat(fmt, a);
fmt = naughty_format;
@@ -223,7 +217,7 @@
bool PruneList::naughty(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
- if (!(*it)->cmp(element)) {
+ if (!(*it).cmp(element)) {
return true;
}
}
@@ -233,7 +227,7 @@
bool PruneList::nice(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
- if (!(*it)->cmp(element)) {
+ if (!(*it).cmp(element)) {
return true;
}
}
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 5f60801..57cd03b 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -19,7 +19,7 @@
#include <sys/types.h>
-#include <utils/List.h>
+#include <list>
#include <LogBufferElement.h>
@@ -47,7 +47,7 @@
void format(char **strp);
};
-typedef android::List<Prune *> PruneCollection;
+typedef std::list<Prune> PruneCollection;
class PruneList {
PruneCollection mNaughty;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b71908c..de143b7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -88,10 +88,17 @@
write /proc/sys/kernel/panic_on_oops 1
write /proc/sys/kernel/hung_task_timeout_secs 0
write /proc/cpu/alignment 4
+
+ # scheduler tunables
+ # Disable auto-scaling of scheduler tunables with hotplug. The tunables
+ # will vary across devices in unpredictable ways if allowed to scale with
+ # cpu cores.
+ write /proc/sys/kernel/sched_tunable_scaling 0
write /proc/sys/kernel/sched_latency_ns 10000000
write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
write /proc/sys/kernel/sched_compat_yield 1
write /proc/sys/kernel/sched_child_runs_first 0
+
write /proc/sys/kernel/randomize_va_space 2
write /proc/sys/kernel/kptr_restrict 2
write /proc/sys/vm/mmap_min_addr 32768
@@ -182,8 +189,11 @@
trigger late-init
# Load properties from /system/ + /factory after fs mount.
-on load_all_props_action
- load_all_props
+on load_system_props_action
+ load_system_props
+
+on load_persist_props_action
+ load_persist_props
start logd
start logd-reinit
@@ -196,12 +206,16 @@
trigger early-fs
trigger fs
trigger post-fs
- trigger post-fs-data
# Load properties from /system/ + /factory after fs mount. Place
# this in another action so that the load will be scheduled after the prior
# issued fs triggers have completed.
- trigger load_all_props_action
+ trigger load_system_props_action
+
+ # Now we can mount /data. File encryption requires keymaster to decrypt
+ # /data, which in turn can only be loaded when system properties are present
+ trigger post-fs-data
+ trigger load_persist_props_action
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
@@ -352,6 +366,8 @@
mkdir /data/system/heapdump 0700 system system
mkdir /data/user 0711 system system
+ setusercryptopolicies /data/user
+
# Reload policy from /data/security if present.
setprop selinux.reload_policy 1
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index e290ca4..6482230 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -89,3 +89,34 @@
# when changing the default configuration
on property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
+
+#
+# USB type C
+#
+
+# USB mode changes
+on property:sys.usb.typec.mode=dfp
+ write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+ setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+on property:sys.usb.typec.mode=ufp
+ write /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}
+ setprop sys.usb.typec.state ${sys.usb.typec.mode}
+
+# USB data role changes
+on property:sys.usb.typec.data_role=device
+ write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+ setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+on property:sys.usb.typec.data_role=host
+ write /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data}
+ setprop sys.usb.typec.state ${sys.usb.typec.data_role}
+
+# USB power role changes
+on property:sys.usb.typec.power_role=source
+ write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+ setprop sys.usb.typec.state ${sys.usb.typec.power_role}
+
+on property:sys.usb.typec.power_role=sink
+ write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power}
+ setprop sys.usb.typec.state ${sys.usb.typec.power_role}