Merge "Fix bug in the way an Event handles a bound thread." into oc-mr1-dev
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 385f03d..6bc0522 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -162,12 +162,29 @@
     return StatusCode::OK;
 }
 
+static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
+    switch (propConfig.prop) {
+        case OBD2_LIVE_FRAME:
+        case OBD2_FREEZE_FRAME:
+        case OBD2_FREEZE_FRAME_CLEAR:
+        case OBD2_FREEZE_FRAME_INFO:
+            return true;
+    }
+    return false;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t supportedAreas = cfg.supportedAreas;
 
+        if (isDiagnosticProperty(cfg)) {
+            // do not write an initial empty value for the diagnostic properties
+            // as we will initialize those separately.
+            continue;
+        }
+
         //  A global property will have supportedAreas = 0
         if (isGlobalProp(cfg.prop)) {
             supportedAreas = 0;
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 235cfef..2ec86b2 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -583,6 +583,67 @@
                             kPortIndexInput, kPortIndexOutput);
 }
 
+// test port mode configuration when the component is in various states
+TEST_F(ComponentHidlTest, PortModeConfig) {
+    description("Test Port Mode Configuration");
+    if (disableTest) return;
+    android::hardware::media::omx::V1_0::Status status;
+    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
+    Message msg;
+
+    status = setRole(omxNode, gEnv->getRole().c_str());
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    OMX_PORT_PARAM_TYPE params;
+    if (compClass == audio_decoder || compClass == audio_encoder) {
+        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
+    } else {
+        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
+    }
+    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(params.nPorts, 2U);
+        kPortIndexInput = params.nStartPortNumber;
+        kPortIndexOutput = kPortIndexInput + 1;
+    }
+
+    android::Vector<BufferInfo> iBuffer, oBuffer;
+
+    // set port mode
+    PortMode portMode[2];
+    initPortMode(portMode, isSecure, compClass);
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
+                            kPortIndexInput, kPortIndexOutput, portMode);
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to executing
+    changeStateIdletoExecute(omxNode, observer);
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    // set state to loaded
+    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
+                            kPortIndexInput, kPortIndexOutput);
+
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+}
+
 // state transitions test
 TEST_F(ComponentHidlTest, StateTransitions) {
     description("Test State Transitions Loaded<->Idle<->Execute");
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 5fe1513..844c44c 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -83,14 +83,20 @@
     RELU6 = 3,
 };
 
-// Two special values that can be used instead of a regular poolIndex.
-enum LocationValues : uint32_t {
-    // The location will be specified at runtime. It's either a temporary
-    // variable, an input, or an output.
-    LOCATION_AT_RUN_TIME = 0xFFFFFFFF,
-    // The operand's value is stored in the
-    // TODO: Only for old
-    LOCATION_SAME_BLOCK = 0xFFFFFFFE
+// How an operand is used.
+enum OperandLifeTime : uint32_t {
+    // The operand is internal to the model.  It's created by an operation
+    // and consumed by other operations.
+    TEMPORARY_VARIABLE,
+    // The operand is an input of the model. An operand can't be both
+    // input and output of a model.
+    MODEL_INPUT,
+    // The operand is an output of the model.
+    MODEL_OUTPUT,
+    // The operand is a constant found in Model.operandValues.
+    CONSTANT_COPY,
+    // The operand is a constant that was specified via a Memory object.
+    CONSTANT_REFERENCE
 };
 
 // Status of a device.
@@ -150,7 +156,20 @@
     float scale;
     int32_t zeroPoint;
 
+    // How the operand is used.
+    OperandLifeTime lifetime;
+
     // Where to find the data for this operand.
+    // If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, or MODEL_OUTPUT:
+    // - All the fields will be 0.
+    // If the lifetime is CONSTANT_COPY:
+    // - location.poolIndex is 0.
+    // - location.offset is the offset in bytes into Model.operandValues.
+    // - location.length is set.
+    // If the lifetime is CONSTANT_REFERENCE:
+    // - location.poolIndex is set.
+    // - location.offset is the offset in bytes into the specified pool.
+    // - location.length is set.
     DataLocation location;
 };
 
@@ -166,12 +185,6 @@
     vec<uint32_t> outputs;
 };
 
-struct InputOutputInfo {
-    DataLocation location;
-    // If dimensions.size() > 0, we have updated dimensions.
-    vec<uint32_t> dimensions;
-};
-
 struct Model {
     vec<Operand> operands;
     vec<Operation> operations;
@@ -181,9 +194,19 @@
     vec<memory> pools;
 };
 
+struct RequestArgument {
+    // The location within one of the memory pools
+    DataLocation location;
+    // If dimensions.size() > 0, dimension information was provided along with the
+    // argument.  This can be the case for models that accept inputs of varying size.
+    // This can't change the rank, just the value of the dimensions that were
+    // unspecified in the model.
+    vec<uint32_t> dimensions;
+};
+
 struct Request {
-    vec<InputOutputInfo> inputs;
-    vec<InputOutputInfo> outputs;
+    vec<RequestArgument> inputs;
+    vec<RequestArgument> outputs;
     vec<memory> pools;
 };
 
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
index bb9f942..90ccd06 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
@@ -103,7 +103,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_AT_RUN_TIME),
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = 0},
         },
@@ -113,7 +114,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_SAME_BLOCK),
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = size},
         },
@@ -123,7 +125,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_SAME_BLOCK),
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0,
                          .offset = size,
                          .length = sizeof(int32_t)},
         },
@@ -133,7 +136,8 @@
             .numberOfConsumers = 0,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_AT_RUN_TIME),
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = 0},
         },
@@ -213,10 +217,10 @@
     // prepare inputs
     uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
     uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
-    std::vector<InputOutputInfo> inputs = {{
+    std::vector<RequestArgument> inputs = {{
         .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
     }};
-    std::vector<InputOutputInfo> outputs = {{
+    std::vector<RequestArgument> outputs = {{
         .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
     }};
     std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),