107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park/**
207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * Copyright (C) 2016 The Android Open Source Project
307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park *
407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * Licensed under the Apache License, Version 2.0 (the "License");
507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * you may not use this file except in compliance with the License.
607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * You may obtain a copy of the License at
707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park *
807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park *      http://www.apache.org/licenses/LICENSE-2.0
907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park *
1007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * Unless required by applicable law or agreed to in writing, software
1107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * distributed under the License is distributed on an "AS IS" BASIS,
1207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * See the License for the specific language governing permissions and
1407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park * limitations under the License.
1507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park */
1607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
1707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#ifndef PLUGIN_LOADER_H_
1807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#define PLUGIN_LOADER_H_
1907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
2007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#include "SharedLibrary.h"
2107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#include <utils/Log.h>
2207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#include <utils/String8.h>
2307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#include <utils/Vector.h>
2407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
2507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parknamespace android {
2607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parknamespace hardware {
2707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parknamespace drm {
2807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parknamespace V1_0 {
2907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parknamespace helper {
3007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
3107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parktemplate <class T>
3207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Parkclass PluginLoader {
3307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
3407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park  public:
3507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    PluginLoader(const char *dir, const char *entry) {
3607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        /**
3707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park         * scan all plugins in the plugin directory and add them to the
3807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park         * factories list.
3907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park         */
4007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        String8 pluginDir(dir);
4107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
4207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        DIR* pDir = opendir(pluginDir.string());
4307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        if (pDir == NULL) {
4407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            ALOGE("Failed to find plugin directory %s", pluginDir.string());
4507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        } else {
4607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            struct dirent* pEntry;
4707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            while ((pEntry = readdir(pDir))) {
4807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                String8 file(pEntry->d_name);
4907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                if (file.getPathExtension() == ".so") {
5007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    String8 path = pluginDir + "/" + pEntry->d_name;
5107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    T *plugin = loadOne(path, entry);
5207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    if (plugin) {
5307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                        factories.push(plugin);
5407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    }
5507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                }
5607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            }
5707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            closedir(pDir);
5807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        }
5907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    }
6007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
6107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    ~PluginLoader() {
6207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        for (size_t i = 0; i < factories.size(); i++) {
6307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            delete factories[i];
6407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        }
6507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    }
6607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
6707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    T *getFactory(size_t i) const {
6807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        return factories[i];
6907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    }
7007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
7107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    size_t factoryCount() const {return factories.size();}
7207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
7307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park  private:
7407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    T* loadOne(const char *path, const char *entry) {
7507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        sp<SharedLibrary> library = new SharedLibrary(String8(path));
7607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        if (!library.get()) {
7707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            ALOGE("Failed to open plugin library %s: %s", path,
7807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    library->lastError());
7907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        } else {
8007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            typedef T *(*CreateFactoryFunc)();
8107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            CreateFactoryFunc createFactoryFunc =
8207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                    (CreateFactoryFunc)library->lookup(entry);
8307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park            if (createFactoryFunc) {
8407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                ALOGV("Found plugin factory entry %s in %s", entry, path);
8507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                libraries.push(library);
8607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                T* result = createFactoryFunc();
8707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park                return  result;
8807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park           }
8907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        }
9007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park        return NULL;
9107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    }
9207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
9307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    Vector<T *> factories;
9407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    Vector<sp<SharedLibrary> > libraries;
9507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
9607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    PluginLoader(const PluginLoader &) = delete;
9707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park    void operator=(const PluginLoader &) = delete;
9807770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park};
9907770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
10007770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park}
10107770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park}
10207770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park}
10307770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park}
10407770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park} // namespace android
10507770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
10607770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park#endif // PLUGIN_LOADER_H_
10707770c78e18c5b09ba116fa1e779fe4408c42e3fJiyong Park
108