summaryrefslogtreecommitdiff
path: root/libs/binder/ndk/service_manager.cpp
blob: 3bfdc59ec26dc3007cd0721b92a8b2c583dcaf82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * Copyright (C) 2018 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 <android/binder_manager.h>
#include <binder/IServiceManager.h>
#include <binder/LazyServiceRegistrar.h>

#include "ibinder_internal.h"
#include "status_internal.h"

using ::android::defaultServiceManager;
using ::android::IBinder;
using ::android::IServiceManager;
using ::android::sp;
using ::android::status_t;
using ::android::statusToString;
using ::android::String16;
using ::android::String8;

binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {
    if (binder == nullptr || instance == nullptr) {
        return EX_ILLEGAL_ARGUMENT;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    status_t exception = sm->addService(String16(instance), binder->getBinder());
    return PruneException(exception);
}

binder_exception_t AServiceManager_addServiceWithFlags(AIBinder* binder, const char* instance,
                                                       const AServiceManager_AddServiceFlag flags) {
    if (binder == nullptr || instance == nullptr) {
        return EX_ILLEGAL_ARGUMENT;
    }

    sp<IServiceManager> sm = defaultServiceManager();

    bool allowIsolated = flags & AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED;
    status_t exception = sm->addService(String16(instance), binder->getBinder(), allowIsolated);
    return PruneException(exception);
}

AIBinder* AServiceManager_checkService(const char* instance) {
    if (instance == nullptr) {
        return nullptr;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->checkService(String16(instance));

    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
    AIBinder_incStrong(ret.get());
    return ret.get();
}
AIBinder* AServiceManager_getService(const char* instance) {
    if (instance == nullptr) {
        return nullptr;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16(instance));

    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
    AIBinder_incStrong(ret.get());
    return ret.get();
}
binder_status_t AServiceManager_registerLazyService(AIBinder* binder, const char* instance) {
    if (binder == nullptr || instance == nullptr) {
        return STATUS_UNEXPECTED_NULL;
    }

    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    status_t status = serviceRegistrar.registerService(binder->getBinder(), instance);

    return PruneStatusT(status);
}
AIBinder* AServiceManager_waitForService(const char* instance) {
    if (instance == nullptr) {
        return nullptr;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->waitForService(String16(instance));

    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
    AIBinder_incStrong(ret.get());
    return ret.get();
}
typedef void (*AServiceManager_onRegister)(const char* instance, AIBinder* registered,
                                           void* cookie);

struct AServiceManager_NotificationRegistration
    : public IServiceManager::LocalRegistrationCallback {
    std::mutex m;
    const char* instance = nullptr;
    void* cookie = nullptr;
    AServiceManager_onRegister onRegister = nullptr;

    virtual void onServiceRegistration(const String16& smInstance, const sp<IBinder>& binder) {
        std::lock_guard<std::mutex> l(m);
        if (onRegister == nullptr) return;

        LOG_ALWAYS_FATAL_IF(String8(smInstance) != instance, "onServiceRegistration: %s != %s",
                            String8(smInstance).c_str(), instance);

        sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
        AIBinder_incStrong(ret.get());

        onRegister(instance, ret.get(), cookie);
    }

    void clear() {
        std::lock_guard<std::mutex> l(m);
        instance = nullptr;
        cookie = nullptr;
        onRegister = nullptr;
    }
};

__attribute__((warn_unused_result)) AServiceManager_NotificationRegistration*
AServiceManager_registerForServiceNotifications(const char* instance,
                                                AServiceManager_onRegister onRegister,
                                                void* cookie) {
    LOG_ALWAYS_FATAL_IF(instance == nullptr, "instance == nullptr");
    LOG_ALWAYS_FATAL_IF(onRegister == nullptr, "onRegister == nullptr for %s", instance);
    // cookie can be nullptr

    auto cb = sp<AServiceManager_NotificationRegistration>::make();
    cb->instance = instance;
    cb->onRegister = onRegister;
    cb->cookie = cookie;

    sp<IServiceManager> sm = defaultServiceManager();
    if (status_t res = sm->registerForNotifications(String16(instance), cb); res != STATUS_OK) {
        ALOGE("Failed to register for service notifications for %s: %s", instance,
              statusToString(res).c_str());
        return nullptr;
    }

    cb->incStrong(nullptr);
    return cb.get();
}

void AServiceManager_NotificationRegistration_delete(
        AServiceManager_NotificationRegistration* notification) {
    LOG_ALWAYS_FATAL_IF(notification == nullptr, "notification == nullptr");
    notification->clear();
    notification->decStrong(nullptr);
}

bool AServiceManager_isDeclared(const char* instance) {
    if (instance == nullptr) {
        return false;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    return sm->isDeclared(String16(instance));
}
void AServiceManager_forEachDeclaredInstance(const char* interface, void* context,
                                             void (*callback)(const char*, void*)) {
    LOG_ALWAYS_FATAL_IF(interface == nullptr, "interface == nullptr");
    // context may be nullptr
    LOG_ALWAYS_FATAL_IF(callback == nullptr, "callback == nullptr");

    sp<IServiceManager> sm = defaultServiceManager();
    for (const String16& instance : sm->getDeclaredInstances(String16(interface))) {
        callback(String8(instance).c_str(), context);
    }
}
bool AServiceManager_isUpdatableViaApex(const char* instance) {
    if (instance == nullptr) {
        return false;
    }

    sp<IServiceManager> sm = defaultServiceManager();
    return sm->updatableViaApex(String16(instance)) != std::nullopt;
}
void AServiceManager_getUpdatableApexName(const char* instance, void* context,
                                          void (*callback)(const char*, void*)) {
    LOG_ALWAYS_FATAL_IF(instance == nullptr, "instance == nullptr");
    // context may be nullptr
    LOG_ALWAYS_FATAL_IF(callback == nullptr, "callback == nullptr");

    sp<IServiceManager> sm = defaultServiceManager();
    std::optional<String16> updatableViaApex = sm->updatableViaApex(String16(instance));
    if (updatableViaApex.has_value()) {
        callback(String8(updatableViaApex.value()).c_str(), context);
    }
}
void AServiceManager_forceLazyServicesPersist(bool persist) {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    serviceRegistrar.forcePersist(persist);
}
void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    std::function<bool(bool)> fn = [=](bool hasClients) -> bool {
        return callback(hasClients, context);
    };
    serviceRegistrar.setActiveServicesCallback(fn);
}
bool AServiceManager_tryUnregister() {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    return serviceRegistrar.tryUnregister();
}
void AServiceManager_reRegister() {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    serviceRegistrar.reRegister();
}