1/**
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef PLUGIN_LOADER_H_
18#define PLUGIN_LOADER_H_
19
20#include "SharedLibrary.h"
21#include <utils/Log.h>
22#include <utils/String8.h>
23#include <utils/Vector.h>
24
25namespace android {
26
27template <class T>
28class PluginLoader {
29
30  public:
31    PluginLoader(const char *dir, const char *entry) {
32        /**
33         * scan all plugins in the plugin directory and add them to the
34         * factories list.
35         */
36        String8 pluginDir(dir);
37
38        DIR* pDir = opendir(pluginDir.string());
39        if (pDir == NULL) {
40            ALOGE("Failed to find plugin directory %s", pluginDir.string());
41        } else {
42            struct dirent* pEntry;
43            while ((pEntry = readdir(pDir))) {
44                String8 file(pEntry->d_name);
45                if (file.getPathExtension() == ".so") {
46                    String8 path = pluginDir + "/" + pEntry->d_name;
47                    T *plugin = loadOne(path, entry);
48                    if (plugin) {
49                        factories.push(plugin);
50                    }
51                }
52            }
53            closedir(pDir);
54        }
55    }
56
57    ~PluginLoader() {
58        for (size_t i = 0; i < factories.size(); i++) {
59            delete factories[i];
60        }
61    }
62
63    T *getFactory(size_t i) const {
64        return factories[i];
65    }
66
67    size_t factoryCount() const {return factories.size();}
68
69  private:
70    T* loadOne(const char *path, const char *entry) {
71        sp<SharedLibrary> library = new SharedLibrary(String8(path));
72        if (!library.get()) {
73            ALOGE("Failed to open plugin library %s: %s", path,
74                    library->lastError());
75        } else {
76            typedef T *(*CreateFactoryFunc)();
77            CreateFactoryFunc createFactoryFunc =
78                    (CreateFactoryFunc)library->lookup(entry);
79            if (createFactoryFunc) {
80                ALOGV("Found plugin factory entry %s in %s", entry, path);
81                libraries.push(library);
82                T* result = createFactoryFunc();
83                return  result;
84           }
85        }
86        return NULL;
87    }
88
89    Vector<T *> factories;
90    Vector<sp<SharedLibrary> > libraries;
91
92    PluginLoader(const PluginLoader &) = delete;
93    void operator=(const PluginLoader &) = delete;
94};
95
96} // namespace android
97
98#endif // PLUGIN_LOADER_H_
99
100