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

Commit 1ea57363 authored by destradaa's avatar destradaa Committed by Android (Google) Code Review
Browse files

Merge "Intern strings used in Sensor information."

parents 28439f26 9ba7c1c1
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
@@ -833,4 +833,96 @@ public final class Sensor {
                + ", type=" + mType + ", maxRange=" + mMaxRange + ", resolution=" + mResolution
                + ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
    }

    /**
     * Sets the Type associated with the sensor.
     * NOTE: to be used only by native bindings in SensorManager.
     *
     * This allows interned static strings to be used across all representations of the Sensor. If
     * a sensor type is not referenced here, it will still be interned by the native SensorManager.
     *
     * @return {@code true} if the StringType was successfully set, {@code false} otherwise.
     */
    private boolean setType(int value) {
        mType = value;
        switch (mType) {
            case TYPE_ACCELEROMETER:
                mStringType = STRING_TYPE_ACCELEROMETER;
                return true;
            case TYPE_AMBIENT_TEMPERATURE:
                mStringType = STRING_TYPE_AMBIENT_TEMPERATURE;
                return true;
            case TYPE_GAME_ROTATION_VECTOR:
                mStringType = STRING_TYPE_GAME_ROTATION_VECTOR;
                return true;
            case TYPE_GEOMAGNETIC_ROTATION_VECTOR:
                mStringType = STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
                return true;
            case TYPE_GLANCE_GESTURE:
                mStringType = STRING_TYPE_GLANCE_GESTURE;
                return true;
            case TYPE_GRAVITY:
                mStringType = STRING_TYPE_GRAVITY;
                return true;
            case TYPE_GYROSCOPE:
                mStringType = STRING_TYPE_GYROSCOPE;
                return true;
            case TYPE_GYROSCOPE_UNCALIBRATED:
                mStringType = STRING_TYPE_GYROSCOPE_UNCALIBRATED;
                return true;
            case TYPE_HEART_RATE:
                mStringType = STRING_TYPE_HEART_RATE;
                return true;
            case TYPE_LIGHT:
                mStringType = STRING_TYPE_LIGHT;
                return true;
            case TYPE_LINEAR_ACCELERATION:
                mStringType = STRING_TYPE_LINEAR_ACCELERATION;
                return true;
            case TYPE_MAGNETIC_FIELD:
                mStringType = STRING_TYPE_MAGNETIC_FIELD;
                return true;
            case TYPE_MAGNETIC_FIELD_UNCALIBRATED:
                mStringType = STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
                return true;
            case TYPE_PICK_UP_GESTURE:
                mStringType = STRING_TYPE_PICK_UP_GESTURE;
                return true;
            case TYPE_PRESSURE:
                mStringType = STRING_TYPE_PRESSURE;
                return true;
            case TYPE_PROXIMITY:
                mStringType = STRING_TYPE_PROXIMITY;
                return true;
            case TYPE_RELATIVE_HUMIDITY:
                mStringType = STRING_TYPE_RELATIVE_HUMIDITY;
                return true;
            case TYPE_ROTATION_VECTOR:
                mStringType = STRING_TYPE_ROTATION_VECTOR;
                return true;
            case TYPE_SIGNIFICANT_MOTION:
                mStringType = STRING_TYPE_SIGNIFICANT_MOTION;
                return true;
            case TYPE_STEP_COUNTER:
                mStringType = STRING_TYPE_STEP_COUNTER;
                return true;
            case TYPE_STEP_DETECTOR:
                mStringType = STRING_TYPE_STEP_DETECTOR;
                return true;
            case TYPE_TILT_DETECTOR:
                mStringType = SENSOR_STRING_TYPE_TILT_DETECTOR;
                return true;
            case TYPE_WAKE_GESTURE:
                mStringType = STRING_TYPE_WAKE_GESTURE;
                return true;
            case TYPE_ORIENTATION:
                mStringType = STRING_TYPE_ORIENTATION;
                return true;
            case TYPE_TEMPERATURE:
                mStringType = STRING_TYPE_TEMPERATURE;
                return true;
            default:
                return false;
        }
    }
}
+53 −9
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#define LOG_TAG "SensorManager"

#include <map>

#include <utils/Log.h>
#include <utils/Looper.h>

@@ -44,7 +46,6 @@ struct SensorOffsets
    jfieldID    vendor;
    jfieldID    version;
    jfieldID    handle;
    jfieldID    type;
    jfieldID    range;
    jfieldID    resolution;
    jfieldID    power;
@@ -55,6 +56,7 @@ struct SensorOffsets
    jfieldID    requiredPermission;
    jfieldID    maxDelay;
    jfieldID    flags;
    jmethodID   setType;
} gSensorOffsets;


@@ -71,7 +73,6 @@ nativeClassInit (JNIEnv *_env, jclass _this)
    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");
    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
@@ -84,6 +85,47 @@ nativeClassInit (JNIEnv *_env, jclass _this)
                                                        "Ljava/lang/String;");
    sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
    sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
    sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
}

/**
 * A key comparator predicate.
 * It is used to intern strings associated with Sensor data.
 * It defines a 'Strict weak ordering' for the interned strings.
 */
class InternedStringCompare {
public:
    bool operator()(const String8* string1, const String8* string2) const {
        if (string1 == NULL) {
            return string2 != NULL;
        }
        return string1->compare(*string2) < 0;
    }
};

/**
 * A localized interning mechanism for Sensor strings.
 * We implement our own interning to avoid the overhead of using java.lang.String#intern().
 * It is common that Vendor, StringType, and RequirePermission data is common between many of the
 * Sensors, by interning the memory usage to represent Sensors is optimized.
 */
static jstring
getInternedString(JNIEnv *env, const String8* string) {
    static std::map<const String8*, jstring, InternedStringCompare> internedStrings;

    jstring internedString;
    std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
    if (iterator != internedStrings.end()) {
        internedString = iterator->second;
    } else {
        jstring localString = env->NewStringUTF(string->string());
        // we are implementing our own interning so expect these strings to be backed by global refs
        internedString = (jstring) env->NewGlobalRef(localString);
        internedStrings.insert(std::make_pair(string, internedString));
        env->DeleteLocalRef(localString);
    }

    return internedString;
}

static jint
@@ -93,20 +135,19 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)

    Sensor const* const* sensorList;
    size_t count = mgr.getSensorList(&sensorList);
    if (size_t(next) >= count)
    if (size_t(next) >= count) {
        return -1;
    }

    Sensor const* const list = sensorList[next];
    const SensorOffsets& sensorOffsets(gSensorOffsets);
    jstring name = env->NewStringUTF(list->getName().string());
    jstring vendor = env->NewStringUTF(list->getVendor().string());
    jstring stringType = env->NewStringUTF(list->getStringType().string());
    jstring requiredPermission = env->NewStringUTF(list->getRequiredPermission().string());
    jstring name = getInternedString(env, &list->getName());
    jstring vendor = getInternedString(env, &list->getVendor());
    jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
    env->SetObjectField(sensor, sensorOffsets.name,      name);
    env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
    env->SetIntField(sensor, sensorOffsets.version,      list->getVersion());
    env->SetIntField(sensor, sensorOffsets.handle,       list->getHandle());
    env->SetIntField(sensor, sensorOffsets.type,         list->getType());
    env->SetFloatField(sensor, sensorOffsets.range,      list->getMaxValue());
    env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
    env->SetFloatField(sensor, sensorOffsets.power,      list->getPowerUsage());
@@ -115,11 +156,14 @@ nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
                     list->getFifoReservedEventCount());
    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
                     list->getFifoMaxEventCount());
    env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
    env->SetObjectField(sensor, sensorOffsets.requiredPermission,
                        requiredPermission);
    env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
    env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
    if (env->CallBooleanMethod(sensor, sensorOffsets.setType, list->getType()) == JNI_FALSE) {
        jstring stringType = getInternedString(env, &list->getStringType());
        env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
    }
    next++;
    return size_t(next) < count ? next : 0;
}