Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2018 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 #include <android-base/logging.h>
     18 #include <android/binder_manager.h>
     19 #include <iface/iface.h>
     20 
     21 #include <android/binder_auto_utils.h>
     22 
     23 using ::android::sp;
     24 using ::android::wp;
     25 
     26 const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
     27 const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
     28 const char* kIFooDescriptor = "my-special-IFoo-class";
     29 
     30 struct IFoo_Class_Data {
     31     sp<IFoo> foo;
     32 };
     33 
     34 void* IFoo_Class_onCreate(void* args) {
     35     IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
     36     // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
     37     // coupled with this.
     38     return static_cast<void*>(foo);
     39 }
     40 
     41 void IFoo_Class_onDestroy(void* userData) {
     42     delete static_cast<IFoo_Class_Data*>(userData);
     43 }
     44 
     45 binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
     46                                       AParcel* out) {
     47     binder_status_t stat = STATUS_FAILED_TRANSACTION;
     48 
     49     sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
     50     CHECK(foo != nullptr) << "Transaction made on already deleted object";
     51 
     52     switch (code) {
     53         case IFoo::DOFOO: {
     54             int32_t valueIn;
     55             int32_t valueOut;
     56             stat = AParcel_readInt32(in, &valueIn);
     57             if (stat != STATUS_OK) break;
     58             stat = foo->doubleNumber(valueIn, &valueOut);
     59             if (stat != STATUS_OK) break;
     60             stat = AParcel_writeInt32(out, valueOut);
     61             break;
     62         }
     63         case IFoo::DIE: {
     64             stat = foo->die();
     65             break;
     66         }
     67     }
     68 
     69     return stat;
     70 }
     71 
     72 AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
     73                                                      IFoo_Class_onDestroy, IFoo_Class_onTransact);
     74 
     75 class BpFoo : public IFoo {
     76    public:
     77     explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
     78     virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
     79 
     80     virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
     81         binder_status_t stat = STATUS_OK;
     82 
     83         AParcel* parcelIn;
     84         stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
     85         if (stat != STATUS_OK) return stat;
     86 
     87         stat = AParcel_writeInt32(parcelIn, in);
     88         if (stat != STATUS_OK) return stat;
     89 
     90         ::ndk::ScopedAParcel parcelOut;
     91         stat = AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, parcelOut.getR(), 0 /*flags*/);
     92         if (stat != STATUS_OK) return stat;
     93 
     94         stat = AParcel_readInt32(parcelOut.get(), out);
     95         if (stat != STATUS_OK) return stat;
     96 
     97         return stat;
     98     }
     99 
    100     virtual binder_status_t die() {
    101         binder_status_t stat = STATUS_OK;
    102 
    103         AParcel* parcelIn;
    104         stat = AIBinder_prepareTransaction(mBinder, &parcelIn);
    105 
    106         ::ndk::ScopedAParcel parcelOut;
    107         stat = AIBinder_transact(mBinder, IFoo::DIE, &parcelIn, parcelOut.getR(), 0 /*flags*/);
    108 
    109         return stat;
    110     }
    111 
    112    private:
    113     // Always assumes one refcount
    114     AIBinder* mBinder;
    115 };
    116 
    117 IFoo::~IFoo() {
    118     AIBinder_Weak_delete(mWeakBinder);
    119 }
    120 
    121 binder_status_t IFoo::addService(const char* instance) {
    122     AIBinder* binder = nullptr;
    123 
    124     if (mWeakBinder != nullptr) {
    125         // one strong ref count of binder
    126         binder = AIBinder_Weak_promote(mWeakBinder);
    127     }
    128     if (binder == nullptr) {
    129         // or one strong refcount here
    130         binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
    131         if (mWeakBinder != nullptr) {
    132             AIBinder_Weak_delete(mWeakBinder);
    133         }
    134         mWeakBinder = AIBinder_Weak_new(binder);
    135     }
    136 
    137     binder_status_t status = AServiceManager_addService(binder, instance);
    138     // Strong references we care about kept by remote process
    139     AIBinder_decStrong(binder);
    140     return status;
    141 }
    142 
    143 sp<IFoo> IFoo::getService(const char* instance, AIBinder** outBinder) {
    144     AIBinder* binder = AServiceManager_getService(instance);  // maybe nullptr
    145     if (binder == nullptr) {
    146         return nullptr;
    147     }
    148 
    149     if (!AIBinder_associateClass(binder, IFoo::kClass)) {
    150         AIBinder_decStrong(binder);
    151         return nullptr;
    152     }
    153 
    154     if (outBinder != nullptr) {
    155         AIBinder_incStrong(binder);
    156         *outBinder = binder;
    157     }
    158 
    159     if (AIBinder_isRemote(binder)) {
    160         sp<IFoo> ret = new BpFoo(binder);  // takes ownership of binder
    161         return ret;
    162     }
    163 
    164     IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
    165 
    166     CHECK(data != nullptr);  // always created with non-null data
    167 
    168     sp<IFoo> ret = data->foo;
    169 
    170     AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
    171     CHECK(held == binder);
    172     AIBinder_decStrong(held);
    173 
    174     AIBinder_decStrong(binder);
    175     return ret;
    176 }
    177