Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2188ff5 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 5600

* changes:
  Rework the property parsing code.
parents 0ca70883 8bc8ce44
Loading
Loading
Loading
Loading
+40 −15
Original line number Diff line number Diff line
@@ -545,15 +545,28 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
            Log.e(TAG, "*Error*: GetAdapterProperties returned NULL");
            return;
        }
        for (int i = 0; i < properties.length; i+=2) {
            String value = null;
            if (mProperties.containsKey(properties[i])) {
                value = mProperties.get(properties[i]);
                value = value + ',' + properties[i+1];
            } else
                value = properties[i+1];

            mProperties.put(properties[i], value);
        for (int i = 0; i < properties.length; i++) {
            String name = properties[i];
            String newValue;
            int len;
            if (name == null) {
                Log.e(TAG, "Error:Adapter Property at index" + i + "is null");
                continue;
            }
            if (name.equals("Devices")) {
                len = Integer.valueOf(properties[++i]);
                if (len != 0)
                    newValue = "";
                else
                    newValue = null;
                for (int j = 0; j < len; j++) {
                    newValue += properties[++i] + ",";
                }
            } else {
                newValue = properties[++i];
            }
            mProperties.put(name, newValue);
        }

        // Add adapter object path property.
@@ -819,15 +832,27 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
            propertyValues = new HashMap<String, String>();
        }

        for (int i = 0; i < properties.length; i+=2) {
            String value = null;
            if (propertyValues.containsKey(properties[i])) {
                value = propertyValues.get(properties[i]);
                value = value + ',' + properties[i+1];
        for (int i = 0; i < properties.length; i++) {
            String name = properties[i];
            String newValue;
            int len;
            if (name == null) {
                Log.e(TAG, "Error: Remote Device Property at index" + i + "is null");
                continue;
            }
            if (name.equals("UUIDs") || name.equals("Nodes")) {
                len = Integer.valueOf(properties[++i]);
                if (len != 0)
                    newValue = "";
                else
                    newValue = null;
                for (int j = 0; j < len; j++) {
                    newValue += properties[++i] + ",";
                }
            } else {
                value = properties[i+1];
                newValue = properties[++i];
            }
            propertyValues.put(properties[i], value);
            propertyValues.put(name, newValue);
        }
        mRemoteDeviceProperties.put(address, propertyValues);
    }
+16 −9
Original line number Diff line number Diff line
@@ -260,11 +260,15 @@ class BluetoothEventLoop {
            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
            mBluetoothService.setProperty(name, propValues[1]);
        } else if (name.equals("Devices")) {
            String value = "";
            for (int i = 1; i < propValues.length; i++) {
            String value = null;
            int len = Integer.valueOf(propValues[1]);
            if (len > 0) {
                value = "";
                for (int i = 2; i < propValues.length; i++) {
                    value = value + propValues[i] + ',';
                }
            mBluetoothService.setProperty(name, value.equals("") ? null : value);
            }
            mBluetoothService.setProperty(name, value);
        } else if (name.equals("Powered")) {
            // bluetoothd has restarted, re-read all our properties.
            // Note: bluez only sends this property change when it restarts.
@@ -303,12 +307,15 @@ class BluetoothEventLoop {
            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
            mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
        } else if (name.equals("UUIDs")) {
            String uuid = "" ;
            for (int i = 1; i < propValues.length; i++) {
            String uuid = null;
            int len = Integer.valueOf(propValues[1]);
            if (len > 0) {
                uuid = "";
                for (int i = 2; i < propValues.length; i++) {
                    uuid = uuid + propValues[i] + ",";
                }
            mBluetoothService.setRemoteDeviceProperty(address, name,
                                                        uuid.equals("") ? null : uuid);
            }
            mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
        }

    }
+172 −208
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ static Properties adapter_properties[] = {
    {"Devices", DBUS_TYPE_ARRAY},
};

typedef union {
    char *str_val;
    int int_val;
    char **array_val;
} property_value;

jfieldID get_field(JNIEnv *env, jclass clazz, const char *member,
                   const char *mtype) {
@@ -466,258 +471,217 @@ void append_variant(DBusMessageIter *iter, int type, void *val)
    dbus_message_iter_close_container(iter, &value_iter);
}

int get_property(DBusMessageIter iter, Properties *properties,
                  int max_num_properties, int *prop_index, property_value *value, int *len) {
    DBusMessageIter prop_val, array_val_iter;
    char *property = NULL;
    uint32_t array_type;
    char *str_val;
    int i, j, type, int_val;

//TODO(): Remove code duplication between parse_properties and
//parse_property_change
jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
                              const int max_num_properties) {
    DBusMessageIter dict_entry, dict, prop_val, device_val, array_val_iter;
    jobjectArray strArray = NULL;
    char * property;
    char values[max_num_properties][256];
    char **uuid_array = NULL;
    char **device_path = NULL;
    char **array_elements = NULL;
    char *string_val;
    uint32_t int_val, bool_val;
    int i, j, k, type, array_type, num_array_elements = 0;
    int ret, num_properties = 0, num_uuids = 0, num_devices = 0;


    jclass stringClass = env->FindClass("java/lang/String");
    DBusError err;
    dbus_error_init(&err);

    for (i = 0; i < max_num_properties; i++)
        memset(values[i], '\0', 128 * sizeof(char));

    if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
        goto failure;
    dbus_message_iter_recurse(iter, &dict);
    do {
        if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
            goto failure;
        dbus_message_iter_recurse(&dict, &dict_entry);
        if (dbus_message_iter_get_arg_type(&dict_entry) != DBUS_TYPE_STRING)
            goto failure;
        dbus_message_iter_get_basic(&dict_entry, &property);
        if (!dbus_message_iter_next(&dict_entry))
            goto failure;
        if (dbus_message_iter_get_arg_type(&dict_entry) != DBUS_TYPE_VARIANT)
            goto failure;

    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
        return -1;
    dbus_message_iter_get_basic(&iter, &property);
    if (!dbus_message_iter_next(&iter))
        return -1;
    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
        return -1;
    for (i = 0; i <  max_num_properties; i++) {
            if (!strncmp(properties[i].name, property, strlen(property))) {
                num_properties ++;
        if (!strncmp(property, properties[i].name, strlen(property)))
            break;
    }
        }
    *prop_index = i;
    if (i == max_num_properties)
            goto failure;
        return -1;

        type = properties[i].type;
        dbus_message_iter_recurse(&dict_entry, &prop_val);
    dbus_message_iter_recurse(&iter, &prop_val);
    type = properties[*prop_index].type;
    if (dbus_message_iter_get_arg_type(&prop_val) != type) {
            LOGE("Property type mismatch in parse_properties: %d, expected:%d",
                 dbus_message_iter_get_arg_type(&prop_val), type);
            goto failure;
        LOGE("Property type mismatch in get_property: %d, expected:%d, index:%d",
             dbus_message_iter_get_arg_type(&prop_val), type, *prop_index);
        return -1;
    }

    switch(type) {
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
            dbus_message_iter_get_basic(&prop_val, &string_val);
            strcpy(values[i], string_val);
        dbus_message_iter_get_basic(&prop_val, &value->str_val);
        *len = 1;
        break;
    case DBUS_TYPE_UINT32:
    case DBUS_TYPE_INT16:
            dbus_message_iter_get_basic(&prop_val, &int_val);
            sprintf(values[i], "%d", int_val);
            break;
    case DBUS_TYPE_BOOLEAN:
            dbus_message_iter_get_basic(&prop_val, &bool_val);
            sprintf(values[i], "%s", bool_val ? "true" : "false");
        dbus_message_iter_get_basic(&prop_val, &int_val);
        value->int_val = int_val;
        *len = 1;
        break;
    case DBUS_TYPE_ARRAY:
        dbus_message_iter_recurse(&prop_val, &array_val_iter);
        array_type = dbus_message_iter_get_arg_type(&array_val_iter);
            num_array_elements = 0;
        *len = 0;
        value->array_val = NULL;
        if (array_type == DBUS_TYPE_OBJECT_PATH ||
            array_type == DBUS_TYPE_STRING){
            j = 0;
            do {
                    num_array_elements++;
               j ++;
            } while(dbus_message_iter_next(&array_val_iter));
            dbus_message_iter_recurse(&prop_val, &array_val_iter);
                // Allocate  an array
                array_elements = (char **)malloc(sizeof(char *) *
                                                 num_array_elements);
                if (!array_elements)
                    goto failure;

            // Allocate  an array of char *
            *len = j;
            char **tmp = (char **)malloc(sizeof(char *) * *len);
            if (!tmp)
                return -1;
            j = 0;
            do {
                   dbus_message_iter_get_basic(&array_val_iter, &array_elements[j]);
               dbus_message_iter_get_basic(&array_val_iter, &tmp[j]);
               j ++;
            } while(dbus_message_iter_next(&array_val_iter));
                if (!strncmp(property, "UUIDs", strlen("UUIDs"))) {
                    num_uuids = num_array_elements;
                    uuid_array = array_elements;
                } else {
                    num_devices = num_array_elements;
                    device_path = array_elements;
                }
            value->array_val = tmp;
        }
        break;
    default:
            goto failure;
        return -1;
    }
    return 0;
}
    } while(dbus_message_iter_next(&dict));

    // Convert it to a array of strings.
    strArray = env->NewObjectArray((num_properties + num_array_elements) * 2,
                                   stringClass, NULL);
void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property,
                       property_value *value, int len, int *array_index ) {
    char **prop_val = NULL;
    char buf[32] = {'\0'}, buf1[32] = {'\0'};
    int i;

    j = 0;
    for (i = 0; i < max_num_properties; i++) {
        if (properties[i].type == DBUS_TYPE_ARRAY) {
            if (!strncmp(properties[i].name, "UUIDs", strlen("UUIDs"))) {
                num_array_elements = num_uuids;
                array_elements = uuid_array;
    char *name = property->name;
    int prop_type = property->type;

    set_object_array_element(env, strArray, name, *array_index);
    *array_index += 1;

    if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) {
        sprintf(buf, "%d", value->int_val);
        set_object_array_element(env, strArray, buf, *array_index);
        *array_index += 1;
    } else if (prop_type == DBUS_TYPE_BOOLEAN) {
        sprintf(buf, "%s", value->int_val ? "true" : "false");

        set_object_array_element(env, strArray, buf, *array_index);
        *array_index += 1;
    } else if (prop_type == DBUS_TYPE_ARRAY) {
        // Write the length first
        sprintf(buf1, "%d", len);
        set_object_array_element(env, strArray, buf1, *array_index);
        *array_index += 1;

        prop_val = value->array_val;
        for (i = 0; i < len; i++) {
            set_object_array_element(env, strArray, prop_val[i], *array_index);
            *array_index += 1;
        }
    } else {
                num_array_elements = num_devices;
                array_elements = device_path;
        set_object_array_element(env, strArray, (const char *) value->str_val, *array_index);
        *array_index += 1;
    }
}

jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties,
                              const int max_num_properties) {
    DBusMessageIter dict_entry, dict;
    jobjectArray strArray = NULL;
    property_value value;
    int i, size = 0,array_index = 0;
    int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type;
    struct {
        property_value value;
        int len;
        bool used;
    } values[max_num_properties];
    int t, j;

            for (k = 0; k < num_array_elements; k++) {
                set_object_array_element(env, strArray, properties[i].name, j++);
                set_object_array_element(env, strArray, array_elements[k], j++);
    jclass stringClass = env->FindClass("java/lang/String");
    DBusError err;
    dbus_error_init(&err);

    for (i = 0; i < max_num_properties; i++) {
        values[i].used = false;
    }
        } else if (values[i][0] != '\0') {
            set_object_array_element(env, strArray, properties[i].name, j++);
            set_object_array_element(env, strArray, values[i], j++);

    if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
        goto failure;
    dbus_message_iter_recurse(iter, &dict);
    do {
        len = 0;
        if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY)
            goto failure;
        dbus_message_iter_recurse(&dict, &dict_entry);

        if (!get_property(dict_entry, properties, max_num_properties, &prop_index,
                          &value, &len)) {
            size += 2;
            if (properties[prop_index].type == DBUS_TYPE_ARRAY)
                size += len;
            values[prop_index].value = value;
            values[prop_index].len = len;
            values[prop_index].used = true;
        } else {
            goto failure;
        }
    } while(dbus_message_iter_next(&dict));

    strArray = env->NewObjectArray(size, stringClass, NULL);

    for (i = 0; i < max_num_properties; i++) {
        if (values[i].used) {
            create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len,
                              &array_index);

            if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used
                   && values[i].value.array_val != NULL)
                free(values[i].value.array_val);
        }

    if (uuid_array)
        free(uuid_array);
    if (device_path)
        free(device_path);
    }
    return strArray;

failure:
    if (dbus_error_is_set(&err))
        LOG_AND_FREE_DBUS_ERROR(&err);
    if (uuid_array)
        free(uuid_array);
    if (device_path)
        free(device_path);
    for (i = 0; i < max_num_properties; i++)
        if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true
                                        && values[i].value.array_val != NULL)
            free(values[i].value.array_val);
    return NULL;
}

jobjectArray create_prop_array(JNIEnv *env, Properties *properties,
                               int prop_index, void *value, int len ) {
    jclass stringClass= env->FindClass("java/lang/String");
    char **prop_val = NULL;
    char buf[32] = {'\0'};
    int i, j;

    jobjectArray strArray = env->NewObjectArray(1 + len, stringClass, NULL);
    j = 0;
    set_object_array_element(env, strArray, properties[prop_index].name, j++);

    if (properties[prop_index].type == DBUS_TYPE_UINT32) {
        sprintf(buf, "%d", *(int *) value);
        set_object_array_element(env, strArray, buf, j++);
    } else if (properties[prop_index].type == DBUS_TYPE_BOOLEAN) {
        sprintf(buf, "%s", *(int *) value ? "true" : "false");
        set_object_array_element(env, strArray, buf, j++);
    } else if (properties[prop_index].type == DBUS_TYPE_ARRAY) {
        prop_val = (char **) value;
        for (i = 0; i < len; i++)
             set_object_array_element(env, strArray, prop_val[i], j++);
    } else {
         set_object_array_element(env, strArray, (const char *) value, j++);
    }
    if (prop_val)
        free (prop_val);
    return strArray;
}

jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg,
                           Properties *properties, int max_num_properties) {
    DBusMessageIter iter, prop_val, array_val_iter;
    DBusMessageIter iter;
    DBusError err;
    void *value;
    char *property;
    uint32_t array_type;
    int i, j, type, len, prop_index;
    jobjectArray strArray = NULL;
    jclass stringClass= env->FindClass("java/lang/String");
    int len = 0, prop_index = -1;
    int array_index = 0, size = 0;
    property_value value;

    dbus_error_init(&err);
    if (!dbus_message_iter_init(msg, &iter))
        goto failure;
    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
        goto failure;
    dbus_message_iter_get_basic(&iter, &property);
    if (!dbus_message_iter_next(&iter))
        goto failure;
    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
        goto failure;
    for (i = 0; i <  max_num_properties; i++) {
        if (!strncmp(property, properties[i].name, strlen(properties[i].name)))
            break;
    }
    prop_index = i;
    if (i == max_num_properties)
        goto failure;

    dbus_message_iter_recurse(&iter, &prop_val);
    type = properties[prop_index].type;
    if (dbus_message_iter_get_arg_type(&prop_val) != type) {
        LOGE("Property type mismatch in parse_properties: %d, expected:%d",
        dbus_message_iter_get_arg_type(&prop_val), type);
        goto failure;
    }
    if (!get_property(iter, properties, max_num_properties,
                      &prop_index, &value, &len)) {
        size += 2;
        if (properties[prop_index].type == DBUS_TYPE_ARRAY)
            size += len;
        strArray = env->NewObjectArray(size, stringClass, NULL);

    switch(type) {
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
        dbus_message_iter_get_basic(&prop_val, &value);
        len = 1;
        break;
    case DBUS_TYPE_UINT32:
    case DBUS_TYPE_INT16:
    case DBUS_TYPE_BOOLEAN:
        uint32_t int_val;
        dbus_message_iter_get_basic(&prop_val, &int_val);
        value = &int_val;
        len = 1;
        break;
    case DBUS_TYPE_ARRAY:
        dbus_message_iter_recurse(&prop_val, &array_val_iter);
        array_type = dbus_message_iter_get_arg_type(&array_val_iter);
        len = 0;
        if (array_type == DBUS_TYPE_OBJECT_PATH ||
            array_type == DBUS_TYPE_STRING){
            do {
                len ++;
            } while(dbus_message_iter_next(&array_val_iter));
            dbus_message_iter_recurse(&prop_val, &array_val_iter);
            // Allocate  an array of char *
            char **tmp = (char **)malloc(sizeof(char *) * len);
            if (!tmp)
                goto failure;
            j = 0;
            do {
               dbus_message_iter_get_basic(&array_val_iter, &tmp[j]);
               j ++;
            } while(dbus_message_iter_next(&array_val_iter));
            value = (char **) tmp;
        }
        break;
    default:
        goto failure;
        create_prop_array(env, strArray, &properties[prop_index],
                          &value, len, &array_index);

        if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL)
             free(value.array_val);

        return strArray;
    }
    return create_prop_array(env, properties, prop_index, value, len);
failure:
    LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
    return NULL;