Saturday, August 3, 2019

Android: Creating custom SDK

Android framework SDK that is published by Google is used by app developers to link to Android framework when they develop Android apps. What if your company needs to add new APIs to the framework? It is not recommended to add this into Android framework SDK and publish customized framework SDK. The ideal method in this case is to publish your custom SDK that contains only the new APIs that is specific to your platform.

Google has already given a template to do this under device/sample. That is a good place to start to make your custom SDK.

Copy device/sample to device/mycompany
Remove unwanted directories like 'overlays', 'etc', 'skins'.

Final directory structure will be as follows:
device
  mycompany
     apps
     frameworks
     |  MycompanyLibrary
     |  |  java
     |  |  |  com
     |  |  |     mycompany
     |  |  |        android
     |  |  |           sdk
     |  |  |              Myfeature.java
     |  |  Android.mk
     |  |  AndroidManifest.xml
     |  |  com.mycompany.android.sdk.xml
     |  |  README.txt
     |  Android.mk
     products
     |  addon_stub_defs
     |  AndroidProducts.mk
     |  mycompany_addon.mk
     |  source.properties
     sdk_addon
     |  hardware.ini
     |  manifest.ini
     Android.mk
     CleanSpec.mk
     README.txt



Implementation for the SDK apis goes under 'device/mycompany/frameworks' directory.

frameworks/MycompanyLibrary/java/com/mycompany/android/sdk
Namespace can be adjusted as per your conventions. In this example namespace is 'java.com.mycompany.sdk'.

Implement your SDK feature in Myfeature.java. If required use JNI to if your implementation requires lower layers.

The list below shows all the changes that are needed in the files that are copied from 'device/sample'.

frameworks/MycompanyLibrary/Android.mk


# Copyright (C) 2008 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.
#

ifneq ($(TARGET_BUILD_JAVA_SUPPORT_LEVEL),)

# This makefile shows how to build your own shared library that can be
# shipped on the system of a phone, and included additional examples of
# including JNI code with the library and writing client applications against it.

LOCAL_PATH := $(call my-dir)

# The jar library
# ============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_MODULE_TAGS := optional

# This is the target being built.
LOCAL_MODULE:= com.mycompany.android.sdk

include $(BUILD_JAVA_LIBRARY)

# The aar library. To be manually made at Android root dir with
#  make out/target/common/obj/JAVA_LIBRARIES/com.mycompany.android.aar.sdk_intermediates/javalib.aar
# ============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= com.mycompany.android.aar.sdk

include $(BUILD_STATIC_JAVA_LIBRARY)

# the documentation
# ============================================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-subdir-html-files)

LOCAL_MODULE:= mycompany_sdk_v1.0.0
LOCAL_DROIDDOC_OPTIONS :=
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_USE_STANDARD_DOCLET := true

include $(BUILD_DROIDDOC)

# The JNI component
# ============================================================
# Also build all of the sub-targets under this one: the library's
# associated JNI code, and a sample client of the library.
include $(CLEAR_VARS)

include $(call all-makefiles-under,$(LOCAL_PATH))

endif # JAVA_SUPPORT


frameworks/MycompanyLibrary/AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
   package="com.mycompany.android.aar.sdk" >
</manifest>


frameworks/MycompanyLibrary/com.mycompany.android.sdk.xml


<?xml version="1.0" encoding="utf-8"?>
<permissions>
    <library name="com.mycompany.android.sdk"
            file="/system/framework/com.mycompany.android.sdk.jar"/>
</permissions>



products/addon_stub_defs

+com.mycompany.android.sdk.*


products/AndroidProducts.mk

# This file should set PRODUCT_MAKEFILES to a list of product makefiles
# to expose to the build system.  LOCAL_DIR will already be set to
# the directory containing this file.
#
# This file may not rely on the value of any variable other than
# LOCAL_DIR; do not use any conditionals, and do not look up the
# value of any variable that isn't set in this file or in a file that
# it includes.
#

PRODUCT_MAKEFILES := \
  $(LOCAL_DIR)/mycompany_addon.mk

products/mycompany_addon.mk

DEVICE_PACKAGE_OVERLAYS := device/qcom/msm8996_gvmq/overlay

#BOARD_COMMON_DIR := device/qcom/common
#BOARD_OPENSOURCE_DIR := device/qcom/msm8909w/opensource
BOARD_DLKM_DIR := device/qcom/common/dlkm
#DEVICE_COMMON_PATH := $(BOARD_COMMON_DIR)

-include device/qcom/common/utils.mk

#$(call inherit-product, $(BOARD_COMMON_DIR)/common.mk)

# List of apps and optional libraries (Java and native) to put in the add-on system image.
PRODUCT_PACKAGES := \
    MycompanyLibraryClient \
 com.mycompany.android.sdk

# Manually copy the optional library XML files in the system image.
PRODUCT_COPY_FILES := \
    device/mycompany/frameworks/MycompanyLibrary/com.mycompany.android.sdk.xml: \
    system/etc/permissions/com.mycompany.android.sdk.xml

# name of the add-on
PRODUCT_SDK_ADDON_NAME := mycompany_sdk_v1.0.0

PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP := $(LOCAL_PATH)/source.properties

# Copy the manifest and hardware files for the SDK add-on.
# The content of those files is manually created for now.
PRODUCT_SDK_ADDON_COPY_FILES := \
    device/mycompany/sdk_addon/manifest.ini:manifest.ini \
    device/mycompany/sdk_addon/hardware.ini:hardware.ini


# Add this to PRODUCT_SDK_ADDON_COPY_FILES to copy the files for an
# emulator skin (or for samples)
#$(call find-copy-subdir-files,*,device/sample/skins/WVGAMedDpi,skins/WVGAMedDpi)

# Copy the jar files for the optional libraries that are exposed as APIs.
PRODUCT_SDK_ADDON_COPY_MODULES := \
    com.mycompany.android.sdk:libs/mycompany_sdk_v1.0.0.jar

# Rules for public APIs
PRODUCT_SDK_ADDON_STUB_DEFS := $(LOCAL_PATH)/addon_stub_defs

# Name of the doc to generate and put in the add-on. This must match the name defined
# in the optional library with the tag
#    LOCAL_MODULE:= platform_library
# in the documentation section.
PRODUCT_SDK_ADDON_DOC_MODULES := mycompany_sdk_v1.0.0

# This add-on extends the default sdk product.

$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk)

# Real name of the add-on. This is the name used to build the add-on.
# Use 'make PRODUCT-<PRODUCT_NAME>-sdk_addon' to build the add-on.
PRODUCT_NAME := mycompany_addon


products/source.properties

Addon.NameId=mycompany_sdk_v1.0.0
Pkg.Desc=Provides the Mycompany APIs to 3rd party apk developer
Addon.VendorId=mycompany
Archive.Arch=ANY
Addon.NameDisplay=MycompanySDK
Addon.VendorDisplay=Mycompany
Archive.Os=ANY
Pkg.Revision=1
AndroidVersion.ApiLevel=19



sdk_addon/manifest.ini

# SDK Add-on Manifest
# File encoding is UTF-8

# Name and vendor of the add-on.
# Add-ons are uniquely identified by a string composed of name, vendor and api.
# 2 add-ons with the same identifier cannot be installed in the same SDK
# and only the add-on with the highest rev number will be installed.
# Name and vendor are used to create folder names, so they shouldn't contain
# any special characters. Also, the character ':' is forbidden.
# Mandatory character set: a-z A-Z 0-9 _.-
name=Mycompany Add-On
vendor=Mycompany
description=mycompany add-on

# version of the Android platform on which this add-on is built.
api=15

# revision of the add-on. This must be a strict integer.
revision=1

# list of libraries, separated by a semi-colon.
# This must be the name of the libraries, as required by the
# <uses-library> node in the AndroidManifest.xml file.
libraries=com.mycompany.android.sdk

# details for each library. format is:
# <library.name>=<name>.jar;<desc>
# where
# <library.name>: the name of the library defined in the property "libraries" above.
# <name>.jar: the jar file containing the library API. This is to be located in
#             the add-on folder in libs/
com.mycompany.android.sdk=mycompany_sdk_v1.0.0.jar;Mycompany SDK

# default skin name. Optional. Only useful if the add-on has its own skin, or
# if it wishes to override the default skin of the base platform.
# This should be the name of the skin in the skins/ folder of the add-on.
#skin=WVGAMedDpi

# USB Vendor ID
# This 16-bit integer allows adb to detect new devices, by extending the list
# of USB Vendor IDs it knows. After installing an add-on the command
# 'android update' adb' must be run to update a file that adb reads during
# start-up.
#usb-vendor=0x0000

README.txt

To make the sdk run

make -j8 PRODUCT-mycompany_addon-sdk_addon

Use the command in README to build the SDK. It will generate mycompany_sdk_v1.0.0.jar that can be used in applications.
It will also generate the sdk libraries to be used on target - 'com.mycompany.android.sdk.xxx' files.

Friday, August 2, 2019

Android: Link third party libraries to your service

AOSP make file structure does not make it easy to link external libraries to your custom service. Here I am outlining a specific way to achieve this.

Create 'libs' folder under your service implementation and put the '.a' or '.so' files in there.
And add Android.mk under 'libs' folder

LOCAL_PATH := $(call my-dir)
PREBUILT_PATH := $(LOCAL_PATH)

include $(CLEAR_VARS)
LOCAL_MODULE        := libMyhal
LOCAL_MODULE_OWNER  := mycompany
LOCAL_MODULE_TAGS   := optional
LOCAL_MODULE_CLASS  := STATIC_LIBRARIES
LOCAL_MODULE_SUFFIX := .a
LOCAL_SRC_FILES     := libMyhal.a
include $(BUILD_PREBUILT)


If you have '.so' file change STATIC_LIBRARIES to SHARED_LIBRARIES.

Now in your service Android.mk file
Add this line
LOCAL_STATIC_LIBRARIES := libMyhal

Also to the end of the file add
include $(call all-makefiles-under,$(LOCAL_PATH))
This line will ensure to invoke the makefile created under 'libs' folder.

Android: Creating custom HIDL

HAL interface definition language(HIDL) is used to interface between HAL and its users. It creates a seamless way to invoke the HAL interface from either Java or cpp. All the inter process communication boiler plate code required is automatically created when the HIDL file is compiled.

This article outlines the method to create your custom HIDL. In this example HIDL interface is created under vendor instead of directly adding onto any other AOSP directories.

Create your hidl interface directory and the sub directories as shown below
vendor/mycompany/proprietary/interfaces/myhal/1.0/default

Now time to create your hidl interface file IMycompanyMyhal.hal

package vendor.mycompany.hardware.myhal@1.0;

interface IMycompanyMyhal {
  /**
   * Starts myhal data streaming
   *
   */
  oneway startMyhal();

  /**
   * Stops myhal data streaming
   *
   */
  oneway stopMyhal();

  /**
   * Gets current myhal state
   *
   */
  getCurrentState() generates (MycompanyMyhalState state);
};


Types needed for your interface should be defined in types.hal. In the interface defined above we use the type 'MycompanyMyhalState' as the type.

package vendor.mycompany.hardware.myhal@1.0;

enum MycompanyMyhalState : int32_t {
  IDLE = 0,
  PLAYING = 1,
  ERROR = 2
};


Create the makefiles Android.bp & Android.mk. You can also use hidl-gen tool to automatically create these files.

Android.bp file example

// This file is autogenerated by hidl-gen. Do not edit manually.

filegroup {
    name: "vendor.mycompany.hardware.myhal@1.0_hal",
    srcs: [
        "types.hal",
        "IMycompanyMyhal.hal",
    ],
}

genrule {
    name: "vendor.mycompany.hardware.myhal@1.0_genc++",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources \
       -randroid.hidl:system/libhidl/transport \
       -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces 
       vendor.mycompany.hardware.myhal@1.0",
    srcs: [
        ":vendor.mycompany.hardware.myhal@1.0_hal",
    ],
    out: [
        "vendor/mycompany/hardware/myhal/1.0/types.cpp",
        "vendor/mycompany/hardware/myhal/1.0/MycompanyMyhalAll.cpp",
    ],
}

genrule {
    name: "vendor.mycompany.hardware.myhal@1.0_genc++_headers",
    tools: ["hidl-gen"],
    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers \
       -randroid.hidl:system/libhidl/transport \
       -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces \
       vendor.mycompany.hardware.myhal@1.0",
    srcs: [
        ":vendor.mycompany.hardware.myhal@1.0_hal",
    ],
    out: [
        "vendor/mycompany/hardware/myhal/1.0/types.h",
        "vendor/mycompany/hardware/myhal/1.0/hwtypes.h",
        "vendor/mycompany/hardware/myhal/1.0/IMycompanyMyhal.h",
        "vendor/mycompany/hardware/myhal/1.0/IHwMycompanyMyhal.h",
        "vendor/mycompany/hardware/myhal/1.0/BnHwMycompanyMyhal.h",
        "vendor/mycompany/hardware/myhal/1.0/BpHwMycompanyMyhal.h",
        "vendor/mycompany/hardware/myhal/1.0/BsMycompanyMyhal.h",
    ],
}

cc_library {
    name: "vendor.mycompany.hardware.myhal@1.0",
    defaults: ["hidl-module-defaults"],
    generated_sources: ["vendor.mycompany.hardware.myhal@1.0_genc++"],
    generated_headers: ["vendor.mycompany.hardware.myhal@1.0_genc++_headers"],
    export_generated_headers: ["vendor.mycompany.hardware.myhal@1.0_genc++_headers"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "liblog",
        "libutils",
        "libcutils",
    ],

    export_shared_lib_headers: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "libutils",
    ],
}

cc_library {
    name: "vendor.mycompany.hardware.myhal@1.0_vendor",
    defaults: ["hidl-module-defaults"],
    generated_sources: ["vendor.mycompany.hardware.myhal@1.0_genc++"],
    generated_headers: ["vendor.mycompany.hardware.myhal@1.0_genc++_headers"],
    export_generated_headers: ["vendor.mycompany.hardware.myhal@1.0_genc++_headers"],
    vendor: true,
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "liblog",
        "libutils",
        "libcutils",
    ],
    export_shared_lib_headers: [
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "libutils",
    ],
}

Android.mk file example
# This file is autogenerated by hidl-gen. Do not edit manually.

LOCAL_PATH := $(call my-dir)

################################################################################
include $(CLEAR_VARS)
LOCAL_MODULE := vendor.mycompany.hardware.myhal-V1.0-java
LOCAL_MODULE_CLASS := JAVA_LIBRARIES

intermediates := $(call local-generated-sources-dir, COMMON)

HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)

LOCAL_JAVA_LIBRARIES := \
    android.hidl.base-V1.0-java \

#
# Build types.hal (MycompanyMyhalState)
#
GEN := $(intermediates)/vendor/mycompany/hardware/myhal/V1_0/MycompanyMyhalState.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hidl:system/libhidl/transport \
        -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces \
        vendor.mycompany.hardware.myhal@1.0::types.MycompanyMyhalState

$(GEN): $(LOCAL_PATH)/types.hal
 $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)

#
# Build IMycompanyMyhal.hal
#
GEN := $(intermediates)/vendor/mycompany/hardware/myhal/V1_0/IMycompanyMyhal.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMycompanyMyhal.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
$(GEN): $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hidl:system/libhidl/transport \
        -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces \
        vendor.mycompany.hardware.myhal@1.0::IMycompanyMyhal

$(GEN): $(LOCAL_PATH)/IMycompanyMyhal.hal
 $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_JAVA_LIBRARY)

################################################################################

include $(CLEAR_VARS)
LOCAL_MODULE := vendor.mycompany.hardware.myhal-V1.0-java-static
LOCAL_MODULE_CLASS := JAVA_LIBRARIES

intermediates := $(call local-generated-sources-dir, COMMON)

HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)

LOCAL_STATIC_JAVA_LIBRARIES := \
    android.hidl.base-V1.0-java-static \

#
# Build types.hal (MycompanyMyhalState)
#
GEN := $(intermediates)/vendor/mycompany/hardware/myhal/V1_0/MycompanyMyhalState.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hidl:system/libhidl/transport \
        -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces \
        vendor.mycompany.hardware.myhal@1.0::types.MycompanyMyhalState

$(GEN): $(LOCAL_PATH)/types.hal
 $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)

#
# Build IMycompanyMyhal.hal
#
GEN := $(intermediates)/vendor/mycompany/hardware/myhal/V1_0/IMycompanyMyhal.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMycompanyMyhal.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
$(GEN): $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
        -Ljava \
        -randroid.hidl:system/libhidl/transport \
        -rvendor.mycompany.hardware:vendor/mycompany/proprietary/interfaces \
        vendor.mycompany.hardware.myhal@1.0::IMycompanyMyhal

$(GEN): $(LOCAL_PATH)/IMycompanyMyhal.hal
 $(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_STATIC_JAVA_LIBRARY)


Now moving onto the real deal, implement the interface. Our default implementation will be under '1.0/default' directory.

First we need to create a main function where the service is started, create 'service.cpp'.

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>

#include "myhal.h"

using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;

int main(int /*argc*/, char** argv) {
  android::base::InitLogging(argv,
                             android::base::LogdLogger(android::base::SYSTEM));
  LOG(INFO) << "Mycompany myhal service booting up...";

  configureRpcThreadpool(1, true /* callerWillJoin */);

  // Setup hwbinder service
  android::sp<vendor::mycompany::hardware::myhal::V1_0::IMycompanyMyhal> service =
      new vendor::mycompany::hardware::myhal::V1_0::MycompanyMyhal();
  CHECK_EQ(service->registerAsService(), android::NO_ERROR)
      << "Failed to register Mycompany myhal service";

  joinRpcThreadpool();

  LOG(INFO) << "Mycompany myhal service is terminating...";
  return 0;
}



Now for the actual implementation of the hal interface
Header file myhal.h

#ifndef MYHAL_H_
#define MYHAL_H_

#include <functional>

#include <android-base/macros.h>
#include <vendor/mycompany/hardware/myhal/1.0/IMycompanyMyhal.h>
#include <utils/Looper.h>

#include "AudioEngine.h"

namespace vendor {
namespace mycompany {
namespace hardware {
namespace myhal {
namespace V1_0 {
using namespace vendor::mycompany::hardware::myhal::V1_0;
using namespace android::hardware;

/**
 * Root HIDL interface object used to control the Myhal HAL.
 */
class MycompanyMyhal : public V1_0::IMycompanyMyhal {
 public:
  MycompanyMyhal();

  //HIDL interfaces
  Return<void> startMyhal() override;
  Return<void> stopMyhal() override;
  Return<MycompanyMyhalState> getMyhalState() override;

 private:
  std::unique_ptr<AudioEngine> myhalEngine_;
  MycompanyMyhalState myhalState_;

  DISALLOW_COPY_AND_ASSIGN(MycompanyMyhal);
};

}  // namespace V1_0
}  // namespace myhal
}  // namespace hardware
}  // namespace mycompany
}  // namespace android

#endif  // MYHAL_H_

Interface implementation in myhal.cpp.

#include <android-base/logging.h>

#include "myhal.h"

namespace vendor {
namespace mycompany {
namespace hardware {
namespace myhal {
namespace V1_0 {

MycompanyMyhal::MycompanyMyhal() : myhalState_(MycompanyMyhalState::IDLE) {
  /* TODO: Do initialization here */
}

Return<void> MycompanyMyhal::startMyhal() {
  /* TODO: Do your logic to start myhal */
  myhalState_ = MycompanyMyhalState::PLAYING;
  return Void();
}

Return<void> MycompanyMyhal::stopMyhal() {
  /* TODO: Do your logic to stop myhal */
  myhalState_ = MycompanyMyhalState::IDLE;
  return Void();
}

Return<MycompanyMyhalState> MycompanyMyhal::getMyhalState() {
  return myhalState_;
}

}  // namespace V1_0
}  // namespace myhal
}  // namespace hardware
}  // namespace mycompany
}  // namespace android


Every service needs an '.rc' file to specify the service name, permissions etc and to start your service automatically - vendor.mycompany.hardware.myhal@1.0-service.rc
service mycompanymyhalservice /vendor/bin/hw/vendor.mycompany.hardware.myhal@1.0-service
    class hal
    user root
    group audio myhal system
    seclabel u:r:shell:s0


We need a makefile to compile this default implementation, so create Android.mk here to compile the implementation
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := vendor.mycompany.hardware.myhal@1.0-service
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
LOCAL_SRC_FILES := \
    myhal.cpp \
    service.cpp

LOCAL_C_INCLUDES := \
    frameworks/av/media/libaaudio/include

LOCAL_SHARED_LIBRARIES := \
    vendor.mycompany.hardware.myhal@1.0 \
    libbase \
    libcutils \
    libhidlbase \
    libhidltransport \
    libaaudio \
    liblog \
    libnl \
    libutils

LOCAL_INIT_RC := vendor.mycompany.hardware.myhal@1.0-service.rc
include $(BUILD_EXECUTABLE)



Android use SELINUX policies to determine which processes to run in the system. To run your service SELINUX permissions needs to be enabled
Most sepolicy is built under system/sepolicy.
But your vendor could override it under device/vendorname/sepolicy/common

Since this is hw service add the component in 'hwservice_contexts' file
vendor.mycompany.hardware.myhal::IMycompanyMyhal        u:object_r:hal_telephony_hwservice:s0

If application needs to find the HIDL interface it needs to be published in manifest file. Add it in one of the manifest.xml file for eg: device/<vendorname>/<platform>/manifest.xml
<!-- Mycompany service -->
    <hal format="hidl">
        <name>vendor.mycompany.hardware.myhal</name>
        <transport>hwbinder</transport>
        <impl level="generic"></impl>
        <version>1.0</version>
        <interface>
            <name>IMycompanyMyhal</name>
            <instance>default</instance>
        </interface>
    </hal>


If SELINUX mode is 'permissive' this should work. If not, to allow our service to run, add 'allow' line in hwservice.te.

After compilation make sure your service is copied to /vendor/bin/hw and the '.rc' file is copied to /vendor/etc/init.
Also your service library('.so') file should be copied to /system/lib and /system/lib64.