add error and hal restart monitoring with other cleanup

- add separate thread dispatch in native VehicleNetwork api.
- fix deadlock in binderDied: do not access HAL with lock held.
- fix missing sp in HandlerThread usage.
- add error listening and hal restart monitoring to binder callback.
- clarified mocking behavior:
  clients listening for global error or HAL restart is not cleared by
  mocking but client subscribing properties are all cleared and should
  subscribe again.
- added native tests and Java tests to test mocking

bug: 24095928
(cherry picked from commit a116a2009ac8966b16cba1ab98d37ad8c537ab02)

Change-Id: I247c64dcb8722a678ed1c2e950a215a193a5e991
diff --git a/libvehiclenetwork/native/HandlerThread.cpp b/libvehiclenetwork/native/HandlerThread.cpp
new file mode 100644
index 0000000..2e15071
--- /dev/null
+++ b/libvehiclenetwork/native/HandlerThread.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 "HandlerThread.h"
+
+namespace android {
+
+HandlerThread::HandlerThread()
+    : mShouldQuit(false) {
+
+}
+
+HandlerThread::~HandlerThread() {
+    quit();
+}
+
+sp<Looper> HandlerThread::getLooper() {
+    Mutex::Autolock autoLock(mLock);
+    if (mLooper.get() == 0) {
+        mLooperWait.wait(mLock);
+    }
+    return mLooper;
+}
+
+status_t HandlerThread::start(const char* name, int32_t priority, size_t stack) {
+    return run(name, priority, stack);
+}
+
+void HandlerThread::quit() {
+    if (!isRunning()) {
+        return;
+    }
+    sp<Looper> looper = getLooper();
+    mLock.lock();
+    mShouldQuit = true;
+    mLock.unlock();
+    looper->wake();
+    requestExitAndWait();
+}
+
+bool HandlerThread::threadLoop() {
+    mLock.lock();
+    mLooper = Looper::prepare(0);
+    mLooperWait.broadcast();
+    mLock.unlock();
+    while (true) {
+        do {
+            Mutex::Autolock autoLock(mLock);
+            if (mShouldQuit) {
+                return false;
+            }
+        } while (false);
+        mLooper->pollOnce(-1);
+    }
+    return false;
+}
+
+
+};
diff --git a/libvehiclenetwork/native/IVehicleNetwork.cpp b/libvehiclenetwork/native/IVehicleNetwork.cpp
index 61fa208..0ceb1a0 100644
--- a/libvehiclenetwork/native/IVehicleNetwork.cpp
+++ b/libvehiclenetwork/native/IVehicleNetwork.cpp
@@ -40,6 +40,11 @@
     INJECT_EVENT,
     START_MOCKING,
     STOP_MOCKING,
+    INJECT_HAL_ERROR,
+    START_ERROR_LISTENING,
+    STOP_ERROR_LISTENING,
+    START_HAL_RESTART_MONITORING,
+    STOP_HAL_RESTART_MONITORING
 };
 
 // ----------------------------------------------------------------------------
@@ -184,6 +189,52 @@
             ALOGI("stop mocking failed %d", status);
         }
     }
+
+    status_t injectHalError(int32_t errorCode, int32_t property, int32_t operation) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
+        data.writeInt32(errorCode);
+        data.writeInt32(property);
+        data.writeInt32(operation);
+        status_t status = remote()->transact(INJECT_HAL_ERROR, data, &reply);
+        return status;
+    }
+
+    virtual status_t startErrorListening(const sp<IVehicleNetworkListener> &listener) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(listener));
+        status_t status = remote()->transact(START_ERROR_LISTENING, data, &reply);
+        return status;
+    }
+
+    virtual void stopErrorListening(const sp<IVehicleNetworkListener> &listener) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(listener));
+        status_t status = remote()->transact(STOP_ERROR_LISTENING, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGI("stopErrorListening %d", status);
+        }
+    }
+
+    virtual status_t startHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(listener));
+        status_t status = remote()->transact(START_HAL_RESTART_MONITORING, data, &reply);
+        return status;
+    }
+
+    virtual void stopHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(listener));
+        status_t status = remote()->transact(STOP_HAL_RESTART_MONITORING, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGI("stopHalRestartMonitoring %d", status);
+        }
+    }
 };
 
 IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);
@@ -326,6 +377,47 @@
             BinderUtil::fillNoResultReply(reply);
             return NO_ERROR;
         } break;
+        case INJECT_HAL_ERROR: {
+            CHECK_INTERFACE(IVehicleNetwork, data, reply);
+            int32_t errorCode = data.readInt32();
+            int32_t property = data.readInt32();
+            int32_t operation = data.readInt32();
+            r = injectHalError(errorCode, property, operation);
+            BinderUtil::fillNoResultReply(reply);
+            return r;
+        } break;
+        case START_ERROR_LISTENING: {
+            CHECK_INTERFACE(IVehicleNetwork, data, reply);
+            sp<IVehicleNetworkListener> listener =
+                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
+            r = startErrorListening(listener);
+            BinderUtil::fillNoResultReply(reply);
+            return r;
+        } break;
+        case STOP_ERROR_LISTENING: {
+            CHECK_INTERFACE(IVehicleNetwork, data, reply);
+            sp<IVehicleNetworkListener> listener =
+                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
+            stopErrorListening(listener);
+            BinderUtil::fillNoResultReply(reply);
+            return NO_ERROR;
+        } break;
+        case START_HAL_RESTART_MONITORING: {
+            CHECK_INTERFACE(IVehicleNetwork, data, reply);
+            sp<IVehicleNetworkListener> listener =
+                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
+            r = startHalRestartMonitoring(listener);
+            BinderUtil::fillNoResultReply(reply);
+            return r;
+        } break;
+        case STOP_HAL_RESTART_MONITORING: {
+            CHECK_INTERFACE(IVehicleNetwork, data, reply);
+            sp<IVehicleNetworkListener> listener =
+                    interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
+            stopHalRestartMonitoring(listener);
+            BinderUtil::fillNoResultReply(reply);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libvehiclenetwork/native/IVehicleNetworkListener.cpp b/libvehiclenetwork/native/IVehicleNetworkListener.cpp
index e83a10c..b8579dc 100644
--- a/libvehiclenetwork/native/IVehicleNetworkListener.cpp
+++ b/libvehiclenetwork/native/IVehicleNetworkListener.cpp
@@ -33,6 +33,8 @@
 
 enum {
     ON_EVENTS = IBinder::FIRST_CALL_TRANSACTION,
+    ON_HAL_ERROR,
+    ON_HAL_RESTART,
 };
 
 class BpVehicleNetworkListener : public BpInterface<IVehicleNetworkListener>
@@ -42,14 +44,15 @@
         : BpInterface<IVehicleNetworkListener>(impl) {
     }
 
-    virtual status_t onEvents(sp<VehiclePropValueListHolder>& events) {
+    virtual void onEvents(sp<VehiclePropValueListHolder>& events) {
         Parcel data, reply;
         data.writeInterfaceToken(IVehicleNetworkListener::getInterfaceDescriptor());
         std::unique_ptr<VehiclePropValues> values(new VehiclePropValues());
         ASSERT_OR_HANDLE_NO_MEMORY(values.get(), return NO_MEMORY);
         status_t r = VehicleNetworkProtoUtil::toVehiclePropValues(events->getList(), *values.get());
         if (r != NO_ERROR) {
-            return r;
+            ALOGE("onEvents: toVehiclePropValues failed %d", r);
+            return;
         }
         data.writeInt32(1); // for java compatibility
         WritableBlobHolder blob(new Parcel::WritableBlob());
@@ -57,8 +60,23 @@
         data.writeInt32(size);
         data.writeBlob(size, false, blob.blob);
         values->SerializeToArray(blob.blob->data(), size);
-        r = remote()->transact(ON_EVENTS, data, &reply);
-        return r;
+        remote()->transact(ON_EVENTS, data, &reply);
+    }
+
+    virtual void onHalError(int32_t errorCode, int32_t property, int32_t operation) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetworkListener::getInterfaceDescriptor());
+        data.writeInt32(errorCode);
+        data.writeInt32(property);
+        data.writeInt32(operation);
+        remote()->transact(ON_HAL_ERROR, data, &reply);
+    }
+
+    virtual void onHalRestart(bool inMocking) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IVehicleNetworkListener::getInterfaceDescriptor());
+        data.writeInt32(inMocking ? 1 : 0);
+        remote()->transact(ON_HAL_RESTART, data, &reply);
     }
 };
 
@@ -98,8 +116,22 @@
                 ALOGE("onEvents: cannot convert data");
                 return BAD_VALUE;
             }
-            r = onEvents(holder);
-            return r;
+            onEvents(holder);
+            return NO_ERROR;
+        } break;
+        case ON_HAL_ERROR: {
+            CHECK_INTERFACE(IVehicleNetworkListener, data, reply);
+            int32_t errorCode = data.readInt32();
+            int32_t property = data.readInt32();
+            int32_t operation = data.readInt32();
+            onHalError(errorCode, property, operation);
+            return NO_ERROR;
+        } break;
+        case ON_HAL_RESTART: {
+            CHECK_INTERFACE(IVehicleNetworkListener, data, reply);
+            bool inMocking = (data.readInt32() == 1);
+            onHalRestart(inMocking);
+            return NO_ERROR;
         } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
diff --git a/libvehiclenetwork/native/VehicleNetwork.cpp b/libvehiclenetwork/native/VehicleNetwork.cpp
index 044d516..c68190e 100644
--- a/libvehiclenetwork/native/VehicleNetwork.cpp
+++ b/libvehiclenetwork/native/VehicleNetwork.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "VehicleNetwork.Lib"
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
@@ -24,6 +25,111 @@
 
 namespace android {
 
+VehicleNetworkEventMessageHandler::VehicleNetworkEventMessageHandler(const sp<Looper>& looper,
+            sp<VehicleNetworkListener>& listener) :
+            mLooper(looper),
+            mListener(listener) {
+
+}
+
+VehicleNetworkEventMessageHandler::~VehicleNetworkEventMessageHandler() {
+    Mutex::Autolock autoLock(mLock);
+    mEvents.clear();
+    for (VehicleHalError* e : mHalErrors) {
+        delete e;
+    }
+    mHalErrors.clear();
+    mHalRestartEvents.clear();
+}
+
+void VehicleNetworkEventMessageHandler::handleHalEvents(sp<VehiclePropValueListHolder>& events) {
+    Mutex::Autolock autoLock(mLock);
+    mEvents.push_back(events);
+    mLooper->sendMessage(this, Message(EVENT_EVENTS));
+}
+
+void VehicleNetworkEventMessageHandler::handleHalError(int32_t errorCode, int32_t property,
+        int32_t operation) {
+    Mutex::Autolock autoLock(mLock);
+    VehicleHalError* error = new VehicleHalError(errorCode, property, operation);
+    if (error == NULL) {
+        ALOGE("VehicleNetworkEventMessageHandler::handleHalError, new failed");
+        return;
+    }
+    mHalErrors.push_back(error);
+    mLooper->sendMessage(this, Message(EVENT_HAL_ERROR));
+}
+
+void VehicleNetworkEventMessageHandler::handleHalRestart(bool inMocking) {
+    Mutex::Autolock autoLock(mLock);
+    mHalRestartEvents.push_back(inMocking);
+    mLooper->sendMessage(this, Message(EVENT_HAL_RESTART));
+}
+
+void VehicleNetworkEventMessageHandler::doHandleHalEvents() {
+    sp<VehiclePropValueListHolder> values;
+    do {
+        Mutex::Autolock autoLock(mLock);
+        if (mEvents.size() > 0) {
+            auto itr = mEvents.begin();
+            values = *itr;
+            mEvents.erase(itr);
+        }
+    } while (false);
+    if (values.get() != NULL) {
+        mListener->onEvents(values);
+    }
+}
+
+void VehicleNetworkEventMessageHandler::doHandleHalError() {
+    VehicleHalError* error = NULL;
+    do {
+        Mutex::Autolock autoLock(mLock);
+        if (mHalErrors.size() > 0) {
+            auto itr = mHalErrors.begin();
+            error = *itr;
+            mHalErrors.erase(itr);
+        }
+    } while (false);
+    if (error != NULL) {
+        mListener->onHalError(error->errorCode, error->property, error->operation);
+        delete error;
+    }
+}
+
+void VehicleNetworkEventMessageHandler::doHandleHalRestart() {
+    bool shouldDispatch = false;
+    bool inMocking = false;
+    do {
+        Mutex::Autolock autoLock(mLock);
+        if (mHalRestartEvents.size() > 0) {
+            auto itr = mHalRestartEvents.begin();
+            inMocking = *itr;
+            mHalRestartEvents.erase(itr);
+            shouldDispatch = true;
+        }
+    } while (false);
+    if (shouldDispatch) {
+        mListener->onHalRestart(inMocking);
+    }
+}
+
+void VehicleNetworkEventMessageHandler::handleMessage(const Message& message) {
+    switch (message.what) {
+    case EVENT_EVENTS:
+        doHandleHalEvents();
+        break;
+    case EVENT_HAL_ERROR:
+        doHandleHalError();
+        break;
+    case EVENT_HAL_RESTART:
+        doHandleHalRestart();
+        break;
+    }
+}
+
+// ----------------------------------------------------------------------------
+
 sp<VehicleNetwork> VehicleNetwork::createVehicleNetwork(sp<VehicleNetworkListener>& listener) {
     sp<IBinder> binder = defaultServiceManager()->getService(
             String16(IVehicleNetwork::SERVICE_NAME));
@@ -32,7 +138,6 @@
         sp<IVehicleNetwork> ivn(interface_cast<IVehicleNetwork>(binder));
         vn = new VehicleNetwork(ivn, listener);
         if (vn != NULL) {
-            binder->linkToDeath(vn);
             // in case thread pool is not started, start it.
             ProcessState::self()->startThreadPool();
         }
@@ -48,6 +153,21 @@
 
 VehicleNetwork::~VehicleNetwork() {
     IInterface::asBinder(mService)->unlinkToDeath(this);
+    mHandlerThread->quit();
+}
+
+void VehicleNetwork::onFirstRef() {
+    mHandlerThread = new HandlerThread();
+    status_t r = mHandlerThread->start("VNS.NATIVE_LOOP");
+    if (r != NO_ERROR) {
+        ALOGE("cannot start handler thread, error:%d", r);
+        return;
+    }
+    sp<VehicleNetworkEventMessageHandler> handler(
+            new VehicleNetworkEventMessageHandler(mHandlerThread->getLooper(), mClientListener));
+    ASSERT_ALWAYS_ON_NO_MEMORY(handler.get());
+    mEventHandler = handler;
+    IInterface::asBinder(mService)->linkToDeath(this);
 }
 
 status_t VehicleNetwork::setInt32Property(int32_t property, int32_t value) {
@@ -144,14 +264,47 @@
     mService->unsubscribe(this, property);
 }
 
+status_t VehicleNetwork::injectEvent(const vehicle_prop_value_t& value) {
+    return mService->injectEvent(value);
+}
+
+status_t VehicleNetwork::startMocking(const sp<IVehicleNetworkHalMock>& mock) {
+    return mService->startMocking(mock);
+}
+
+void VehicleNetwork::stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
+    mService->stopMocking(mock);
+}
+
+status_t VehicleNetwork::startErrorListening() {
+    return mService->startErrorListening(this);
+}
+
+void VehicleNetwork::stopErrorListening() {
+    mService->stopErrorListening(this);
+}
+
+status_t VehicleNetwork::startHalRestartMonitoring() {
+    return mService->startHalRestartMonitoring(this);
+}
+
+void VehicleNetwork::stopHalRestartMonitoring() {
+    mService->stopHalRestartMonitoring(this);
+}
+
 void VehicleNetwork::binderDied(const wp<IBinder>& who) {
-    //TODO
+    //TODO recover or notify and give up?
 }
 
-status_t VehicleNetwork::onEvents(sp<VehiclePropValueListHolder>& events) {
-    //TODO call this in separate thread to prevent blocking VNS
-    mClientListener->onEvents(events);
-    return NO_ERROR;
+void VehicleNetwork::onEvents(sp<VehiclePropValueListHolder>& events) {
+    mEventHandler->handleHalEvents(events);
 }
 
+void VehicleNetwork::onHalError(int32_t errorCode, int32_t property, int32_t operation) {
+    mEventHandler->handleHalError(errorCode, property, operation);
+}
+
+void VehicleNetwork::onHalRestart(bool inMocking) {
+    mEventHandler->handleHalRestart(inMocking);
+}
 }; // namespace android