xref: /aosp_15_r20/external/fbjni/test/jni/hybrid_tests.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant /*
2*65c59e02SInna Palant  * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant  *
4*65c59e02SInna Palant  * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant  * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant  * You may obtain a copy of the License at
7*65c59e02SInna Palant  *
8*65c59e02SInna Palant  *     http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant  *
10*65c59e02SInna Palant  * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant  * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant  * See the License for the specific language governing permissions and
14*65c59e02SInna Palant  * limitations under the License.
15*65c59e02SInna Palant  */
16*65c59e02SInna Palant 
17*65c59e02SInna Palant #include <fbjni/fbjni.h>
18*65c59e02SInna Palant #include <condition_variable>
19*65c59e02SInna Palant #include <mutex>
20*65c59e02SInna Palant 
21*65c59e02SInna Palant using namespace facebook::jni;
22*65c59e02SInna Palant 
23*65c59e02SInna Palant class TestException : public std::runtime_error {
24*65c59e02SInna Palant  public:
TestException()25*65c59e02SInna Palant   TestException() : std::runtime_error("fail") {}
26*65c59e02SInna Palant };
27*65c59e02SInna Palant 
28*65c59e02SInna Palant // The C++ half of a hybrid class must extend HybridClass like this.
29*65c59e02SInna Palant // HybridClass is default constructible.
30*65c59e02SInna Palant class TestHybridClass : public facebook::jni::HybridClass<TestHybridClass> {
31*65c59e02SInna Palant  public:
32*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
33*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$TestHybridClass;";
34*65c59e02SInna Palant 
TestHybridClass()35*65c59e02SInna Palant   TestHybridClass() {}
36*65c59e02SInna Palant 
TestHybridClass(int i,std::string s,bool b)37*65c59e02SInna Palant   TestHybridClass(int i, std::string s, bool b)
38*65c59e02SInna Palant       : i_(i), s_(std::move(s)), b_(b) {}
39*65c59e02SInna Palant 
40*65c59e02SInna Palant   // The C++ implementation of initHybrid must be a static C++ method,
41*65c59e02SInna Palant   // since it has no C++ instance (it creates it).  But it's a normal
42*65c59e02SInna Palant   // java method, because it gets a java this passed in (which is
43*65c59e02SInna Palant   // often unused).  It must call makeCxxInstance and return its
44*65c59e02SInna Palant   // result.
45*65c59e02SInna Palant   static jhybriddata
initHybrid(alias_ref<jhybridobject>,jint i,jstring s,jboolean b)46*65c59e02SInna Palant   initHybrid(alias_ref<jhybridobject>, jint i, jstring s, jboolean b) {
47*65c59e02SInna Palant     // The arguments will be forwarded to the ctor, and the result
48*65c59e02SInna Palant     // will be saved in mHybridPointer in the java object.
49*65c59e02SInna Palant     return makeCxxInstance(i, wrap_alias(s)->toStdString(), b).release();
50*65c59e02SInna Palant   }
initHybrid2(alias_ref<jhybridobject>)51*65c59e02SInna Palant   static local_ref<jhybriddata> initHybrid2(alias_ref<jhybridobject>) {
52*65c59e02SInna Palant     return makeCxxInstance();
53*65c59e02SInna Palant   }
54*65c59e02SInna Palant   // It's also ok to make initHybrid work like a factory, which
55*65c59e02SInna Palant   // eliminates the need to define a ctor and reduces boilerplate
56*65c59e02SInna Palant   // code.  This is a member, so fields can be initialized directly.
57*65c59e02SInna Palant   static local_ref<jhybriddata>
initHybrid3(alias_ref<jhybridobject>,std::string s,int i,bool b)58*65c59e02SInna Palant   initHybrid3(alias_ref<jhybridobject>, std::string s, int i, bool b) {
59*65c59e02SInna Palant     auto cxxPart = std::unique_ptr<TestHybridClass>(new TestHybridClass);
60*65c59e02SInna Palant     cxxPart->s_ = std::move(s);
61*65c59e02SInna Palant     cxxPart->i_ = i;
62*65c59e02SInna Palant     cxxPart->b_ = b;
63*65c59e02SInna Palant     return makeHybridData(std::move(cxxPart));
64*65c59e02SInna Palant   }
65*65c59e02SInna Palant 
getInt()66*65c59e02SInna Palant   jint getInt() {
67*65c59e02SInna Palant     return i_;
68*65c59e02SInna Palant   }
69*65c59e02SInna Palant 
getString()70*65c59e02SInna Palant   std::string getString() {
71*65c59e02SInna Palant     return s_;
72*65c59e02SInna Palant   }
73*65c59e02SInna Palant 
getCharString()74*65c59e02SInna Palant   const char* getCharString() {
75*65c59e02SInna Palant     return s_.c_str();
76*65c59e02SInna Palant   }
77*65c59e02SInna Palant 
setBoth(int i,std::string s)78*65c59e02SInna Palant   void setBoth(int i, std::string s) {
79*65c59e02SInna Palant     i_ = i;
80*65c59e02SInna Palant     s_ = s;
81*65c59e02SInna Palant   }
82*65c59e02SInna Palant 
copy1(alias_ref<jhybridobject> other)83*65c59e02SInna Palant   bool copy1(alias_ref<jhybridobject> other) {
84*65c59e02SInna Palant     i_ = cthis(other)->i_;
85*65c59e02SInna Palant     s_ = cthis(other)->s_;
86*65c59e02SInna Palant     return true;
87*65c59e02SInna Palant   }
88*65c59e02SInna Palant 
89*65c59e02SInna Palant   // This returns a boolean to test more code paths, not for any
90*65c59e02SInna Palant   // functional reason.
copy2(TestHybridClass * other)91*65c59e02SInna Palant   jboolean copy2(TestHybridClass* other) {
92*65c59e02SInna Palant     i_ = other->i_;
93*65c59e02SInna Palant     s_ = other->s_;
94*65c59e02SInna Palant     return true;
95*65c59e02SInna Palant   }
96*65c59e02SInna Palant 
oops()97*65c59e02SInna Palant   void oops() {
98*65c59e02SInna Palant     throw TestException();
99*65c59e02SInna Palant   }
100*65c59e02SInna Palant 
setGlobal(alias_ref<jstring> str)101*65c59e02SInna Palant   void setGlobal(alias_ref<jstring> str) {
102*65c59e02SInna Palant     global_ = make_global(str);
103*65c59e02SInna Palant   }
104*65c59e02SInna Palant 
getGlobal1()105*65c59e02SInna Palant   global_ref<jstring> getGlobal1() {
106*65c59e02SInna Palant     return global_;
107*65c59e02SInna Palant   }
108*65c59e02SInna Palant 
getGlobal2()109*65c59e02SInna Palant   const global_ref<jstring>& getGlobal2() {
110*65c59e02SInna Palant     return global_;
111*65c59e02SInna Palant   }
112*65c59e02SInna Palant 
makeWithTwo(alias_ref<jclass> jthis)113*65c59e02SInna Palant   static jhybridobject makeWithTwo(alias_ref<jclass> jthis) {
114*65c59e02SInna Palant     // The args are passed to java, with autoconversion.
115*65c59e02SInna Palant     return newObjectJavaArgs(2, "two", true).release();
116*65c59e02SInna Palant   }
117*65c59e02SInna Palant 
makeWithThree(alias_ref<jclass> jthis)118*65c59e02SInna Palant   static local_ref<jhybridobject> makeWithThree(alias_ref<jclass> jthis) {
119*65c59e02SInna Palant     // The args are passed to C++ initialization directly.
120*65c59e02SInna Palant     return newObjectCxxArgs(3, "three", true);
121*65c59e02SInna Palant   }
122*65c59e02SInna Palant 
mapException(std::exception_ptr ex)123*65c59e02SInna Palant   static void mapException(std::exception_ptr ex) {
124*65c59e02SInna Palant     try {
125*65c59e02SInna Palant       std::rethrow_exception(ex);
126*65c59e02SInna Palant     } catch (const TestException& ex) {
127*65c59e02SInna Palant       throwNewJavaException("java/lang/ArrayStoreException", "");
128*65c59e02SInna Palant     }
129*65c59e02SInna Palant   }
130*65c59e02SInna Palant 
autoconvertMany(alias_ref<jclass>)131*65c59e02SInna Palant   static void autoconvertMany(alias_ref<jclass>) {
132*65c59e02SInna Palant     // Autoconversion to jstring creates a local ref.  Make sure is is
133*65c59e02SInna Palant     // released properly.  The default local table size is 512.
134*65c59e02SInna Palant     for (int i = 0; i < 1000; ++i) {
135*65c59e02SInna Palant       newObjectJavaArgs(1000, "thousand", false);
136*65c59e02SInna Palant       newObjectJavaArgs(1001, make_jstring("thousand+1"), false);
137*65c59e02SInna Palant     }
138*65c59e02SInna Palant   }
139*65c59e02SInna Palant 
140*65c59e02SInna Palant   // Declaring a register function for each class makes it easy to
141*65c59e02SInna Palant   // manage the process.
registerNatives()142*65c59e02SInna Palant   static void registerNatives() {
143*65c59e02SInna Palant     registerHybrid({
144*65c59e02SInna Palant         // Test registration of static method returning void.
145*65c59e02SInna Palant         makeNativeMethod("initHybrid", TestHybridClass::initHybrid),
146*65c59e02SInna Palant         // overloaded members are ugly to get pointers to.  Use a
147*65c59e02SInna Palant         // different name for each C++ method to keep things readable.
148*65c59e02SInna Palant         makeNativeMethod("initHybrid", TestHybridClass::initHybrid2),
149*65c59e02SInna Palant         makeNativeMethod("initHybrid", TestHybridClass::initHybrid3),
150*65c59e02SInna Palant         // C++ members can be registered directly.  The C++ instance
151*65c59e02SInna Palant         // created by makeCxxInstance will be retrieved from the
152*65c59e02SInna Palant         // HybridData, and the method will be invoked with the
153*65c59e02SInna Palant         // arguments passed to java.  These test registration of
154*65c59e02SInna Palant         // method pointers returning non-void.
155*65c59e02SInna Palant         makeNativeMethod("getInt", TestHybridClass::getInt),
156*65c59e02SInna Palant         makeNativeMethod("getString", TestHybridClass::getString),
157*65c59e02SInna Palant         makeNativeMethod("getCharString", TestHybridClass::getCharString),
158*65c59e02SInna Palant         makeNativeMethod("setBoth", TestHybridClass::setBoth),
159*65c59e02SInna Palant         makeNativeMethod("copy1", TestHybridClass::copy1),
160*65c59e02SInna Palant         makeNativeMethod("copy2", TestHybridClass::copy2),
161*65c59e02SInna Palant         makeNativeMethod("oops", TestHybridClass::oops),
162*65c59e02SInna Palant         makeNativeMethod("setGlobal", TestHybridClass::setGlobal),
163*65c59e02SInna Palant         makeNativeMethod("getGlobal1", TestHybridClass::getGlobal1),
164*65c59e02SInna Palant         makeNativeMethod("getGlobal2", TestHybridClass::getGlobal2),
165*65c59e02SInna Palant         makeNativeMethod("makeWithTwo", TestHybridClass::makeWithTwo),
166*65c59e02SInna Palant         makeNativeMethod("makeWithThree", TestHybridClass::makeWithThree),
167*65c59e02SInna Palant         makeNativeMethod("autoconvertMany", TestHybridClass::autoconvertMany),
168*65c59e02SInna Palant     });
169*65c59e02SInna Palant   }
170*65c59e02SInna Palant 
171*65c59e02SInna Palant  private:
172*65c59e02SInna Palant   friend HybridBase;
173*65c59e02SInna Palant 
174*65c59e02SInna Palant   int i_ = 0;
175*65c59e02SInna Palant   std::string s_;
176*65c59e02SInna Palant   bool b_ = false;
177*65c59e02SInna Palant   global_ref<jstring> global_;
178*65c59e02SInna Palant };
179*65c59e02SInna Palant 
180*65c59e02SInna Palant class AbstractTestHybrid
181*65c59e02SInna Palant     : public facebook::jni::HybridClass<AbstractTestHybrid> {
182*65c59e02SInna Palant  public:
183*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
184*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$AbstractTestHybrid;";
185*65c59e02SInna Palant 
AbstractTestHybrid(int nn)186*65c59e02SInna Palant   AbstractTestHybrid(int nn) : nativeNum_(nn) {}
187*65c59e02SInna Palant 
nativeNum()188*65c59e02SInna Palant   int nativeNum() {
189*65c59e02SInna Palant     return nativeNum_;
190*65c59e02SInna Palant   }
191*65c59e02SInna Palant   // This is different than the java method!
192*65c59e02SInna Palant   virtual int sum() = 0;
193*65c59e02SInna Palant 
registerNatives()194*65c59e02SInna Palant   static void registerNatives() {
195*65c59e02SInna Palant     registerHybrid({
196*65c59e02SInna Palant         makeNativeMethod("nativeNum", AbstractTestHybrid::nativeNum),
197*65c59e02SInna Palant     });
198*65c59e02SInna Palant   }
199*65c59e02SInna Palant 
200*65c59e02SInna Palant  private:
201*65c59e02SInna Palant   int nativeNum_;
202*65c59e02SInna Palant };
203*65c59e02SInna Palant 
204*65c59e02SInna Palant class ConcreteTestHybrid
205*65c59e02SInna Palant     : public facebook::jni::
206*65c59e02SInna Palant           HybridClass<ConcreteTestHybrid, AbstractTestHybrid> {
207*65c59e02SInna Palant  public:
208*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
209*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$ConcreteTestHybrid;";
210*65c59e02SInna Palant 
initHybrid(alias_ref<jclass>,int nn,int cn)211*65c59e02SInna Palant   static local_ref<jhybriddata> initHybrid(alias_ref<jclass>, int nn, int cn) {
212*65c59e02SInna Palant     return makeCxxInstance(nn, cn);
213*65c59e02SInna Palant   }
214*65c59e02SInna Palant 
concreteNum()215*65c59e02SInna Palant   int concreteNum() {
216*65c59e02SInna Palant     return concreteNum_;
217*65c59e02SInna Palant   }
sum()218*65c59e02SInna Palant   int sum() override {
219*65c59e02SInna Palant     return nativeNum() + concreteNum();
220*65c59e02SInna Palant   }
221*65c59e02SInna Palant 
registerNatives()222*65c59e02SInna Palant   static void registerNatives() {
223*65c59e02SInna Palant     registerHybrid({
224*65c59e02SInna Palant         makeNativeMethod("initHybrid", ConcreteTestHybrid::initHybrid),
225*65c59e02SInna Palant         makeNativeMethod("concreteNum", ConcreteTestHybrid::concreteNum),
226*65c59e02SInna Palant     });
227*65c59e02SInna Palant   }
228*65c59e02SInna Palant 
229*65c59e02SInna Palant  private:
230*65c59e02SInna Palant   friend HybridBase;
ConcreteTestHybrid(int nn,int cn)231*65c59e02SInna Palant   ConcreteTestHybrid(int nn, int cn) : HybridBase(nn), concreteNum_(cn) {}
232*65c59e02SInna Palant 
233*65c59e02SInna Palant   int concreteNum_;
234*65c59e02SInna Palant };
235*65c59e02SInna Palant 
cxxTestInheritance(alias_ref<jclass>,AbstractTestHybrid * ath)236*65c59e02SInna Palant static jboolean cxxTestInheritance(alias_ref<jclass>, AbstractTestHybrid* ath) {
237*65c59e02SInna Palant   bool ret = true;
238*65c59e02SInna Palant 
239*65c59e02SInna Palant   ret &= ath->nativeNum() == 5;
240*65c59e02SInna Palant   ret &= ath->sum() == 11;
241*65c59e02SInna Palant 
242*65c59e02SInna Palant   auto cth = dynamic_cast<ConcreteTestHybrid*>(ath);
243*65c59e02SInna Palant 
244*65c59e02SInna Palant   ret &= cth != nullptr;
245*65c59e02SInna Palant   ret &= cth->concreteNum() == 6;
246*65c59e02SInna Palant 
247*65c59e02SInna Palant   return ret;
248*65c59e02SInna Palant }
249*65c59e02SInna Palant 
makeAbstractHybrid(alias_ref<jclass>)250*65c59e02SInna Palant static local_ref<AbstractTestHybrid::jhybridobject> makeAbstractHybrid(
251*65c59e02SInna Palant     alias_ref<jclass>) {
252*65c59e02SInna Palant   auto cth = ConcreteTestHybrid::newObjectJavaArgs(0, 0, 0);
253*65c59e02SInna Palant   weak_ref<ConcreteTestHybrid::jhybridobject> wcth = make_weak(cth);
254*65c59e02SInna Palant   weak_ref<AbstractTestHybrid::jhybridobject> wath = wcth;
255*65c59e02SInna Palant 
256*65c59e02SInna Palant   local_ref<AbstractTestHybrid::jhybridobject> ath = cth;
257*65c59e02SInna Palant   return ConcreteTestHybrid::newObjectJavaArgs(
258*65c59e02SInna Palant       cthis(ath)->nativeNum() + 7, 8, 9);
259*65c59e02SInna Palant }
260*65c59e02SInna Palant 
261*65c59e02SInna Palant struct Base : public JavaClass<Base> {
262*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
263*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$Base;";
264*65c59e02SInna Palant };
265*65c59e02SInna Palant 
266*65c59e02SInna Palant class Derived : public HybridClass<Derived, Base> {
267*65c59e02SInna Palant  public:
268*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
269*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$Derived;";
270*65c59e02SInna Palant 
271*65c59e02SInna Palant  private:
272*65c59e02SInna Palant   friend HybridBase;
Derived()273*65c59e02SInna Palant   Derived() {}
274*65c59e02SInna Palant };
275*65c59e02SInna Palant 
276*65c59e02SInna Palant struct Destroyable : public HybridClass<Destroyable> {
277*65c59e02SInna Palant  public:
278*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
279*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$Destroyable;";
280*65c59e02SInna Palant 
~DestroyableDestroyable281*65c59e02SInna Palant   ~Destroyable() override {
282*65c59e02SInna Palant     std::lock_guard<std::mutex> lk(*mtx_);
283*65c59e02SInna Palant     *dead_ = true;
284*65c59e02SInna Palant     cv_->notify_one();
285*65c59e02SInna Palant   }
286*65c59e02SInna Palant 
287*65c59e02SInna Palant   using HybridBase::makeCxxInstance;
288*65c59e02SInna Palant 
289*65c59e02SInna Palant  private:
290*65c59e02SInna Palant   friend HybridBase;
DestroyableDestroyable291*65c59e02SInna Palant   Destroyable(
292*65c59e02SInna Palant       std::shared_ptr<std::mutex> mtx,
293*65c59e02SInna Palant       std::shared_ptr<bool> dead,
294*65c59e02SInna Palant       std::shared_ptr<std::condition_variable> cv)
295*65c59e02SInna Palant       : mtx_(mtx), dead_(dead), cv_(cv) {}
296*65c59e02SInna Palant 
297*65c59e02SInna Palant   std::shared_ptr<std::mutex> mtx_;
298*65c59e02SInna Palant   std::shared_ptr<bool> dead_;
299*65c59e02SInna Palant   std::shared_ptr<std::condition_variable> cv_;
300*65c59e02SInna Palant };
301*65c59e02SInna Palant 
cxxTestHybridDestruction(alias_ref<jclass>)302*65c59e02SInna Palant static jboolean cxxTestHybridDestruction(alias_ref<jclass>) {
303*65c59e02SInna Palant   auto mtx = std::make_shared<std::mutex>();
304*65c59e02SInna Palant   auto dead = std::make_shared<bool>(false);
305*65c59e02SInna Palant   auto cv = std::make_shared<std::condition_variable>();
306*65c59e02SInna Palant   Destroyable::makeCxxInstance(mtx, dead, cv);
307*65c59e02SInna Palant   std::unique_lock<std::mutex> lk(*mtx);
308*65c59e02SInna Palant   cv->wait(lk, [&] { return dead; });
309*65c59e02SInna Palant   return JNI_TRUE;
310*65c59e02SInna Palant }
311*65c59e02SInna Palant 
cxxTestDerivedJavaClass(alias_ref<jclass>)312*65c59e02SInna Palant static jboolean cxxTestDerivedJavaClass(alias_ref<jclass>) {
313*65c59e02SInna Palant   bool ret = true;
314*65c59e02SInna Palant 
315*65c59e02SInna Palant   auto derivedJava = Derived::newObjectCxxArgs();
316*65c59e02SInna Palant 
317*65c59e02SInna Palant   ret &= derivedJava ? true : false;
318*65c59e02SInna Palant   ret &= derivedJava->isInstanceOf(Derived::javaClassLocal());
319*65c59e02SInna Palant   ret &= derivedJava->isInstanceOf(Base::javaClassLocal());
320*65c59e02SInna Palant 
321*65c59e02SInna Palant   auto javaPtr = derivedJava.get();
322*65c59e02SInna Palant 
323*65c59e02SInna Palant   ret &= dynamic_cast<Derived::javaobject>(javaPtr) != nullptr;
324*65c59e02SInna Palant   ret &= dynamic_cast<Base::javaobject>(javaPtr) != nullptr;
325*65c59e02SInna Palant   ret &= dynamic_cast<jobject>(javaPtr) != nullptr;
326*65c59e02SInna Palant 
327*65c59e02SInna Palant   return ret;
328*65c59e02SInna Palant }
329*65c59e02SInna Palant 
330*65c59e02SInna Palant class TestHybridClassBase
331*65c59e02SInna Palant     : public facebook::jni::HybridClass<TestHybridClassBase> {
332*65c59e02SInna Palant  public:
333*65c59e02SInna Palant   static constexpr const char* const kJavaDescriptor =
334*65c59e02SInna Palant       "Lcom/facebook/jni/HybridTests$TestHybridClassBase;";
335*65c59e02SInna Palant 
TestHybridClassBase()336*65c59e02SInna Palant   TestHybridClassBase() {}
337*65c59e02SInna Palant 
TestHybridClassBase(int i)338*65c59e02SInna Palant   explicit TestHybridClassBase(int i) : i_(i) {}
339*65c59e02SInna Palant 
initHybrid(alias_ref<jhybridobject> o,jint i)340*65c59e02SInna Palant   static void initHybrid(alias_ref<jhybridobject> o, jint i) {
341*65c59e02SInna Palant     // The arguments will be forwarded to the ctor, and the result
342*65c59e02SInna Palant     // will be saved in mHybridPointer in the java object.
343*65c59e02SInna Palant     setCxxInstance(o, i);
344*65c59e02SInna Palant   }
345*65c59e02SInna Palant 
initHybrid2(alias_ref<jhybridobject> o)346*65c59e02SInna Palant   static void initHybrid2(alias_ref<jhybridobject> o) {
347*65c59e02SInna Palant     setCxxInstance(o);
348*65c59e02SInna Palant   }
349*65c59e02SInna Palant 
getInt()350*65c59e02SInna Palant   virtual jint getInt() {
351*65c59e02SInna Palant     return i_;
352*65c59e02SInna Palant   }
353*65c59e02SInna Palant 
setInt(int i)354*65c59e02SInna Palant   void setInt(int i) {
355*65c59e02SInna Palant     i_ = i;
356*65c59e02SInna Palant   }
357*65c59e02SInna Palant 
makeWithThree(alias_ref<jclass>)358*65c59e02SInna Palant   static local_ref<jhybridobject> makeWithThree(
359*65c59e02SInna Palant       alias_ref<jclass> /* unused */) {
360*65c59e02SInna Palant     // The args are passed to C++ initialization directly.
361*65c59e02SInna Palant     return newObjectCxxArgs(3);
362*65c59e02SInna Palant   }
363*65c59e02SInna Palant 
registerNatives()364*65c59e02SInna Palant   static void registerNatives() {
365*65c59e02SInna Palant     registerHybrid({
366*65c59e02SInna Palant         makeNativeMethod("initHybrid", TestHybridClassBase::initHybrid),
367*65c59e02SInna Palant         makeNativeMethod("initHybrid", TestHybridClassBase::initHybrid2),
368*65c59e02SInna Palant         makeNativeMethod("getInt", TestHybridClassBase::getInt),
369*65c59e02SInna Palant         makeNativeMethod("setInt", TestHybridClassBase::setInt),
370*65c59e02SInna Palant         makeNativeMethod("makeWithThree", TestHybridClassBase::makeWithThree),
371*65c59e02SInna Palant     });
372*65c59e02SInna Palant   }
373*65c59e02SInna Palant 
374*65c59e02SInna Palant  private:
375*65c59e02SInna Palant   int i_ = 0;
376*65c59e02SInna Palant };
377*65c59e02SInna Palant 
RegisterTestHybridClass()378*65c59e02SInna Palant void RegisterTestHybridClass() {
379*65c59e02SInna Palant   TestHybridClass::registerNatives();
380*65c59e02SInna Palant   AbstractTestHybrid::registerNatives();
381*65c59e02SInna Palant   ConcreteTestHybrid::registerNatives();
382*65c59e02SInna Palant   TestHybridClassBase::registerNatives();
383*65c59e02SInna Palant 
384*65c59e02SInna Palant   registerNatives(
385*65c59e02SInna Palant       "com/facebook/jni/HybridTests",
386*65c59e02SInna Palant       {
387*65c59e02SInna Palant           makeNativeMethod("cxxTestInheritance", cxxTestInheritance),
388*65c59e02SInna Palant           makeNativeMethod("makeAbstractHybrid", makeAbstractHybrid),
389*65c59e02SInna Palant           makeNativeMethod("cxxTestDerivedJavaClass", cxxTestDerivedJavaClass),
390*65c59e02SInna Palant           makeNativeMethod(
391*65c59e02SInna Palant               "cxxTestHybridDestruction", cxxTestHybridDestruction),
392*65c59e02SInna Palant       });
393*65c59e02SInna Palant }
394