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 STAGEFRIGHT_FOUNDATION_A_DATA_H_
18 #define STAGEFRIGHT_FOUNDATION_A_DATA_H_
19 
20 #include <memory> // for std::shared_ptr, weak_ptr and unique_ptr
21 #include <type_traits> // for std::aligned_union
22 
23 #include <utils/StrongPointer.h> // for android::sp and wp
24 
25 #include <media/stagefright/foundation/TypeTraits.h>
26 #include <media/stagefright/foundation/Flagged.h>
27 
28 #undef HIDE
29 #define HIDE __attribute__((visibility("hidden")))
30 
31 // The internals of AUnion cause problems with CFI
32 #undef  NO_CFI
33 #define NO_CFI __attribute__((no_sanitize("cfi")))
34 
35 namespace android {
36 
37 /**
38  * AData is a flexible union type that supports non-POD members. It supports arbitrary types as long
39  * as they are either moveable or copyable.
40  *
41  * Internally, AData is using AUnion - a structure providing the union support. AUnion should not
42  * be used by generic code as it is very unsafe - it opens type aliasing errors where an object of
43  * one type can be easily accessed as an object of another type. AData prevents this.
44  *
45  * AData allows a custom type flagger to be used for future extensions (e.g. allowing automatic
46  * type conversion). A strict and a relaxed flagger are provided as internal types.
47  *
48  * Use as follows:
49  *
50  * AData<int, float>::Basic data; // strict type support
51  * int i = 1;
52  * float f = 7.0f;
53  *
54  * data.set(5);
55  * EXPECT_TRUE(data.find(&i));
56  * EXPECT_FALSE(data.find(&f));
57  * EXPECT_EQ(i, 5);
58  *
59  * data.set(6.0f);
60  * EXPECT_FALSE(data.find(&i));
61  * EXPECT_TRUE(data.find(&f));
62  * EXPECT_EQ(f, 6.0f);
63  *
64  * AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support
65  * sp<ABuffer> buf = new ABuffer(16), buf2;
66  * sp<RefBase> obj;
67  *
68  * objdata.set(buf);
69  * EXPECT_TRUE(objdata.find(&buf2));
70  * EXPECT_EQ(buf, buf2);
71  * EXPECT_FALSE(objdata.find(&i));
72  * EXPECT_TRUE(objdata.find(&obj));
73  * EXPECT_TRUE(obj == buf);
74  *
75  * obj = buf;
76  * objdata.set(obj); // storing as sp<RefBase>
77  * EXPECT_FALSE(objdata.find(&buf2));  // not stored as ABuffer(!)
78  * EXPECT_TRUE(objdata.find(&obj));
79  */
80 
81 /// \cond Internal
82 
83 /**
84  * Helper class to call constructor and destructor for a specific type in AUnion.
85  * This class is needed as member function specialization is not allowed for a
86  * templated class.
87  */
88 struct HIDE _AUnion_impl {
89     /**
90      * Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
91      * Storage MUST be large enough to contain T.
92      * Also clears the slack space after type T. \todo This is not technically needed, so we may
93      * choose to do this just for debugging.
94      *
95      * \param totalSize size of the storage
96      * \param addr      pointer to where object T should be constructed
97      * \param args      arbitrary arguments for constructor
98      */
99     template<typename T, typename ...Args>
emplace_AUnion_impl100     inline static void NO_CFI emplace(size_t totalSize, T *addr, Args&&... args) {
101         new(addr)T(std::forward<Args>(args)...);
102         // clear slack space - this is not technically required
103         constexpr size_t size = sizeof(T);
104         memset(reinterpret_cast<uint8_t*>(addr) + size, 0, totalSize - size);
105     }
106 
107     /**
108      * Calls destuctor for an object of type T located at a specific address.
109      *
110      * \note we do not clear the storage in this case as the storage should not be used
111      * until another object is placed there, at which case the storage will be cleared.
112      *
113      * \param addr    pointer to where object T is stored
114      */
115     template<typename T>
del_AUnion_impl116     inline static void del(T *addr) {
117         addr->~T();
118     }
119 };
120 
121 /** Constructor specialization for void type */
122 template<>
123 HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
124     memset(addr, 0, totalSize);
125 }
126 
127 /** Destructor specialization for void type */
128 template<>
129 HIDE inline void _AUnion_impl::del<void>(void *) {
130 }
131 
132 /// \endcond
133 
134 /**
135  * A templated union class that can contain specific types of data, and provides
136  * constructors, destructor and access methods strictly for those types.
137  *
138  * \note This class is VERY UNSAFE compared to a union, but it allows non-POD unions.
139  * In particular care must be taken that methods are called in a careful order to
140  * prevent accessing objects of one type as another type. This class provides no
141  * facilities to help with this ordering. This is meant to be wrapped by safer
142  * utility classes that do that.
143  *
144  * \param Ts types stored in this union.
145  */
146 template<typename ...Ts>
147 struct AUnion {
148 private:
149     using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type
150     _type mValue;                                              ///< storage
151 
152 public:
153     /**
154      * Constructs an object of type T with arbitrary arguments in this union. After this call,
155      * this union will contain this object.
156      *
157      * This method MUST be called only when either 1) no object or 2) a void object (equivalent to
158      * no object) is contained in this union.
159      *
160      * \param T     type of object to be constructed. This must be one of the template parameters of
161      *              the union class with the same cv-qualification, or void.
162      * \param args  arbitrary arguments for the constructor
163      */
164     template<
165             typename T, typename ...Args,
166             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
emplaceAUnion167     inline void NO_CFI emplace(Args&&... args) {
168         _AUnion_impl::emplace(
169                 sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
170     }
171 
172     /**
173      * Destructs an object of type T in this union. After this call, this union will contain no
174      * object.
175      *
176      * This method MUST be called only when this union contains an object of type T.
177      *
178      * \param T     type of object to be destructed. This must be one of the template parameters of
179      *              the union class with the same cv-qualification, or void.
180      */
181     template<
182             typename T,
183             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
delAUnion184     inline void del() {
185         _AUnion_impl::del(reinterpret_cast<T*>(&mValue));
186     }
187 
188     /**
189      * Returns a const reference to the object of type T in this union.
190      *
191      * This method MUST be called only when this union contains an object of type T.
192      *
193      * \param T     type of object to be returned. This must be one of the template parameters of
194      *              the union class with the same cv-qualification.
195      */
196     template<
197             typename T,
198             typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
getAUnion199     inline const T &get() const {
200         return *reinterpret_cast<const T*>(&mValue);
201     }
202 
203     /**
204      * Returns a reference to the object of type T in this union.
205      *
206      * This method MUST be called only when this union contains an object of type T.
207      *
208      * \param T     type of object to be returned. This must be one of the template parameters of
209      *              the union class with the same cv-qualification.
210      */
211     template<typename T>
getAUnion212     inline T &get() {
213         return *reinterpret_cast<T*>(&mValue);
214     }
215 };
216 
217 /**
218  * Helper utility class that copies an object of type T to a destination.
219  *
220  * T must be copy assignable or copy constructible.
221  *
222  * It provides:
223  *
224  * void assign(T*, const U&) // for copiable types - this leaves the source unchanged, hence const.
225  *
226  * \param T type of object to assign to
227  */
228 template<
229         typename T,
230         bool=std::is_copy_assignable<T>::value>
231 struct HIDE _AData_copier {
232     static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
233 
234     /**
235      * Copies src to data without modifying data.
236      *
237      * \param data pointer to destination
238      * \param src source object
239      */
assign_AData_copier240     inline static void assign(T *data, const T &src) {
241         *data = src;
242     }
243 
244     template<typename U>
245     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
246 
247     /**
248      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
249      */
250     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
assign_AData_copier251     inline static void assign(sp<Tp> *data, const sp<U> &src) {
252         *data = static_cast<Tp*>(src.get());
253     }
254 
255     template<typename Tp, typename U, typename=enable_if_T_is_same_as<wp<Tp>>>
assign_AData_copier256     inline static void assign(wp<Tp> *data, const wp<U> &src) {
257         sp<U> __tmp = src.promote();
258         *data = static_cast<Tp*>(__tmp.get());
259     }
260 
261     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
assign_AData_copier262     inline static void assign(sp<Tp> *data, sp<U> &&src) {
263         sp<U> __tmp = std::move(src); // move src out as get cannot
264         *data = static_cast<Tp*>(__tmp.get());
265     }
266 
267     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
assign_AData_copier268     inline static void assign(std::shared_ptr<Tp> *data, const std::shared_ptr<U> &src) {
269         *data = std::static_pointer_cast<Tp>(src);
270     }
271 
272     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
assign_AData_copier273     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
274         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
275         *data = std::static_pointer_cast<Tp>(__tmp);
276     }
277 
278     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::weak_ptr<Tp>>>
assign_AData_copier279     inline static void assign(std::weak_ptr<Tp> *data, const std::weak_ptr<U> &src) {
280         *data = std::static_pointer_cast<Tp>(src.lock());
281     }
282 
283     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
284     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
285     // they are stored as shared_ptrs.
286     /**
287      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
288      * is not enough to detect this, only if someone is trying to find the shared_ptr.
289      */
290     template<typename Tp, typename U>
assign_AData_copier291     inline static void assign(std::shared_ptr<Tp> *, const std::weak_ptr<U> &) {
292         static_assert(std::is_same<Tp, void>::value,
293                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
294     }
295 };
296 
297 /**
298  * Template specialization for non copy assignable, but copy constructible types.
299  *
300  * \todo Test this. No basic classes are copy constructible but not assignable.
301  *
302  */
303 template<typename T>
304 struct HIDE _AData_copier<T, false> {
305     static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
306     static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
307 
308     inline static void copy(T *data, const T &src) {
309         data->~T();
310         new(data)T(src);
311     }
312 };
313 
314 /**
315  * Helper utility class that moves an object of type T to a destination.
316  *
317  * T must be move assignable or move constructible.
318  *
319  * It provides multiple methods:
320  *
321  * void assign(T*, T&&)
322  *
323  * \param T type of object to assign
324  */
325 template<
326         typename T,
327         bool=std::is_move_assignable<T>::value>
328 struct HIDE _AData_mover {
329     static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
330 
331     /**
332      * Moves src to data while likely modifying it.
333      *
334      * \param data pointer to destination
335      * \param src source object
336      */
337     inline static void assign(T *data, T &&src) {
338         *data = std::move(src);
339     }
340 
341     template<typename U>
342     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
343 
344     /**
345      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
346      */
347     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
348     inline static void assign(sp<Tp> *data, sp<U> &&src) {
349         sp<U> __tmp = std::move(src); // move src out as get cannot
350         *data = static_cast<Tp*>(__tmp.get());
351     }
352 
353     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
354     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
355         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
356         *data = std::static_pointer_cast<Tp>(__tmp);
357     }
358 
359     template<typename Tp, typename Td, typename U, typename Ud,
360             typename=enable_if_T_is_same_as<std::unique_ptr<Tp, Td>>>
361     inline static void assign(std::unique_ptr<Tp, Td> *data, std::unique_ptr<U, Ud> &&src) {
362         *data = std::unique_ptr<Tp, Td>(static_cast<Tp*>(src.release()));
363     }
364 
365     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
366     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
367     // they are stored as shared_ptrs.
368     /**
369      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
370      * is not enough to detect this, only if someone is trying to remove the shared_ptr.
371      */
372     template<typename Tp, typename U>
373     inline static void assign(std::shared_ptr<Tp> *, std::weak_ptr<U> &&) {
374         static_assert(std::is_same<Tp, void>::value,
375                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
376     }
377 
378     // unique_ptrs are implicitly convertible to shared_ptrs but not vice versa, but picking the
379     // first compatible type in Ts requires having unique_ptrs types before shared_ptrs types, so
380     // that they are stored as unique_ptrs.
381     /**
382      * Provide sensible error message if encountering shared_ptr/unique_ptr ambiguity. This method
383      * is not enough to detect this, only if someone is trying to remove the unique_ptr.
384      */
385     template<typename Tp, typename U>
386     inline static void assign(std::unique_ptr<Tp> *, std::shared_ptr<U> &&) {
387         static_assert(std::is_same<Tp, void>::value,
388                       "unique/shared pointer ambiguity. move unique ptr types before shared_ptrs");
389     }
390 };
391 
392 /**
393  * Template specialization for non move assignable, but move constructible types.
394  *
395  * \todo Test this. No basic classes are move constructible but not assignable.
396  *
397  */
398 template<typename T>
399 struct HIDE _AData_mover<T, false> {
400     static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
401     static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
402 
403     inline static void assign(T *data, T &&src) {
404         data->~T();
405         new(data)T(std::move(src));
406     }
407 };
408 
409 /**
410  * Helper template that deletes an object of a specific type (member) in an AUnion.
411  *
412  * \param Flagger type flagger class (see AData)
413  * \param U AUnion object in which the member should be deleted
414  * \param Ts types to consider for the member
415  */
416 template<typename Flagger, typename U, typename ...Ts>
417 struct HIDE _AData_deleter;
418 
419 /**
420  * Template specialization when there are still types to consider (T and rest)
421  */
422 template<typename Flagger, typename U, typename T, typename ...Ts>
423 struct HIDE _AData_deleter<Flagger, U, T, Ts...> {
424     static bool del(typename Flagger::type flags, U &data) {
425         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
426             data.template del<T>();
427             return true;
428         }
429         return _AData_deleter<Flagger, U, Ts...>::del(flags, data);
430     }
431 };
432 
433 /**
434  * Template specialization when there are no more types to consider.
435  */
436 template<typename Flagger, typename U>
437 struct HIDE _AData_deleter<Flagger, U> {
438     inline static bool del(typename Flagger::type, U &) {
439         return false;
440     }
441 };
442 
443 /**
444  * Helper template that copy assigns an object of a specific type (member) in an
445  * AUnion.
446  *
447  * \param Flagger type flagger class (see AData)
448  * \param U AUnion object in which the member should be copy assigned
449  * \param Ts types to consider for the member
450  */
451 template<typename Flagger, typename U, typename ...Ts>
452 struct HIDE _AData_copy_assigner;
453 
454 /**
455  * Template specialization when there are still types to consider (T and rest)
456  */
457 template<typename Flagger, typename U, typename T, typename ...Ts>
458 struct HIDE _AData_copy_assigner<Flagger, U, T, Ts...> {
459     static bool assign(typename Flagger::type flags, U &dst, const U &src) {
460         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
461         // if we can delete as, we can also assign as
462         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
463             dst.template emplace<T>(src.template get<T>());
464             return true;
465         }
466         return _AData_copy_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
467     }
468 };
469 
470 /**
471  * Template specialization when there are no more types to consider.
472  */
473 template<typename Flagger, typename U>
474 struct HIDE _AData_copy_assigner<Flagger, U> {
475     inline static bool assign(typename Flagger::type, U &, const U &) {
476         return false;
477     }
478 };
479 
480 /**
481  * Helper template that move assigns an object of a specific type (member) in an
482  * AUnion.
483  *
484  * \param Flagger type flagger class (see AData)
485  * \param U AUnion object in which the member should be copy assigned
486  * \param Ts types to consider for the member
487  */
488 template<typename Flagger, typename U, typename ...Ts>
489 struct HIDE _AData_move_assigner;
490 
491 /**
492  * Template specialization when there are still types to consider (T and rest)
493  */
494 template<typename Flagger, typename U, typename T, typename ...Ts>
495 struct HIDE _AData_move_assigner<Flagger, U, T, Ts...> {
496     template<typename V = T>
497     static typename std::enable_if<std::is_move_constructible<V>::value, bool>::type
498     assign(typename Flagger::type flags, U &dst, U &src) {
499         // if we can delete as, we can also assign as
500         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
501             dst.template emplace<T>(std::move(src.template get<T>()));
502             return true;
503         }
504         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
505     }
506 
507     // Fall back to copy construction if T is not move constructible
508     template<typename V = T>
509     static typename std::enable_if<!std::is_move_constructible<V>::value, bool>::type
510     assign(typename Flagger::type flags, U &dst, U &src) {
511         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
512         // if we can delete as, we can also assign as
513         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
514             dst.template emplace<T>(src.template get<T>());
515             return true;
516         }
517         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
518     }
519 };
520 
521 /**
522  * Template specialization when there are no more types to consider.
523  */
524 template<typename Flagger, typename U>
525 struct HIDE _AData_move_assigner<Flagger, U> {
526     inline static bool assign(typename Flagger::type, U &, U &) {
527         return false;
528     }
529 };
530 
531 /**
532  * Container that can store an arbitrary object of a set of specified types.
533  *
534  * This struct is an outer class that contains various inner classes based on desired type
535  * strictness. The following inner classes are supported:
536  *
537  * AData<types...>::Basic   - strict type support using uint32_t flag.
538  *
539  * AData<types...>::Strict<Flag> - strict type support using custom flag.
540  * AData<types...>::Relaxed<Flag, MaxSize, Align>
541  *                          - relaxed type support with compatible (usually derived) class support
542  *                            for pointer types with added size checking for minimal additional
543  *                            safety.
544  *
545  * AData<types...>::RelaxedBasic - strict type support using uint32_t flag.
546  *
547  * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types
548  *                                    and the base type to use for each)
549  *
550  */
551 template<typename ...Ts>
552 struct AData {
553 private:
554     static_assert(are_unique<Ts...>::value, "types must be unique");
555 
556     static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support
557 
558 public:
559     /**
560      * Default (strict) type flagger provided.
561      *
562      * The default flagger simply returns the index of the type within Ts, or 0 for void.
563      *
564      * Type flaggers return a flag for a supported type.
565      *
566      * They must provide:
567      *
568      * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no
569      *   object is stored in the container. For this, an arbitrary unique value may be returned.
570      * - a mask field that contains the flag mask.
571      * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be
572      *   deleted as another type.
573      *
574      * \param Flag the underlying unsigned integral to use for the flags.
575      */
576     template<typename Flag>
577     struct flagger {
578     private:
579         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
580         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
581 
582         static constexpr Flag count = num_types + 1;
583 
584     public:
585         typedef Flag type; ///< flag type
586 
587         static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask
588 
589         /**
590          * Return the stored type for T. This is itself.
591          */
592         template<typename T>
593         struct store {
594             typedef T as_type; ///< the base type that T is stored as
595         };
596 
597         /**
598          * Constexpr method that returns if two flags are compatible for deletion.
599          *
600          * \param objectFlag flag for object to be deleted
601          * \param deleteFlag flag for type that object is to be deleted as
602          */
603         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
604             // default flagger requires strict type equality
605             return objectFlag == deleteFlag;
606         }
607 
608         /**
609          * Constexpr method that returns the flag to use for a given type.
610          *
611          * Function overload for void*.
612          */
613         static constexpr Flag flagFor(void*) {
614             return 0u;
615         }
616 
617         /**
618          * Constexpr method that returns the flag to use for a given supported type (T).
619          */
620         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
621         static constexpr Flag flagFor(T*) {
622             return find_first<T, Ts...>::index;
623         }
624     };
625 
626     /**
627      * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns
628      * the first type in Ts that T* can be converted into (this is normally a base type, but also
629      * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also
630      * contains the size of the class to avoid finding objects that were stored as a different
631      * derived class of the same base class.
632      *
633      * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus
634      * the size of the type (divided by alignment) for derived pointer types.
635      *
636      * \param MaxSize max supported size for derived class pointers
637      * \param Align alignment to assume for derived class pointers
638      */
639     template<typename Flag, size_t MaxSize=1024, size_t Align=4>
640     struct relaxed_flagger {
641     private:
642         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
643         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
644 
645         static constexpr Flag count = num_types + 1;
646         static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align),
647                       "not enough bits to fit into flag");
648 
649         static constexpr Flag max_size_stored = MaxSize / Align + 1;
650 
651         // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts
652         template<typename T, size_t size>
653         using enable_if_can_be_converted = typename std::enable_if<
654                 (size / Align < max_size_stored
655                         && find_first_convertible_to<T, Ts...>::index)>::type;
656 
657 
658         template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>>
659         static constexpr Flag relaxedFlagFor(W*, T*) {
660             return find_first_convertible_to<W, Ts...>::index * max_size_stored
661                     + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align));
662         }
663 
664     public:
665         typedef Flag type; ///< flag type
666 
667         static constexpr Flag mask =
668             _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask
669 
670         /**
671          * Constexpr method that returns if two flags are compatible for deletion.
672          *
673          * \param objectFlag flag for object to be deleted
674          * \param deleteFlag flag for type that object is to be deleted as
675          */
676         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
677             // can delete if objects have the same base type
678             return
679                 objectFlag / max_size_stored == deleteFlag / max_size_stored &&
680                 (deleteFlag % max_size_stored) == 0;
681         }
682 
683         /**
684          * Constexpr method that returns the flag to use for a given type.
685          *
686          * Function overload for void*.
687          */
688         static constexpr Flag flagFor(void*) {
689             return 0u;
690         }
691 
692         /**
693          * Constexpr method that returns the flag to use for a given supported type (T).
694          *
695          * This is a member method to enable both overloading as well as template specialization.
696          */
697         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
698         static constexpr Flag flagFor(T*) {
699             return find_first<T, Ts...>::index * max_size_stored;
700         }
701 
702         /**
703          * For precaution, we only consider converting pointers to their base classes.
704          */
705 
706         /**
707          * Template specialization for derived class pointers and managed pointers.
708          */
709         template<typename T>
710         static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); }
711         template<typename T>
712         static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
713         template<typename T>
714         static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
715         template<typename T>
716         static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
717         template<typename T>
718         static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); }
719         template<typename T>
720         static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); }
721 
722         /**
723          * Type support template that provodes the stored type for T.
724          * This is itself if it is one of Ts, or the first type in Ts that T is convertible to.
725          *
726          * NOTE: This template may provide a base class for an unsupported type. Support is
727          * determined by flagFor().
728          */
729         template<typename T>
730         struct store {
731             typedef typename std::conditional<
732                     is_one_of<T, Ts...>::value,
733                     T,
734                     typename find_first_convertible_to<T, Ts...>::type>::type as_type;
735         };
736     };
737 
738     /**
739      * Implementation of AData.
740      */
741     template<typename Flagger>
742     struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> {
743         using data_t = AUnion<Ts...>;
744         using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>;
745 
746         /**
747          * Constructor. Initializes this to a container that does not contain any object.
748          */
749         Custom() : base_t(Flagger::flagFor((void*)0)) { }
750 
751         /**
752          * Copy assignment operator.
753          */
754         Custom& operator=(const Custom &o) {
755             if (&o != this) {
756                 if (this->used() && !this->clear()) {
757                     __builtin_trap();
758                 }
759                 if (o.used()) {
760                     if (_AData_copy_assigner<Flagger, data_t, Ts...>::assign(
761                             o.flags(), this->get(), o.get())) {
762                         this->setFlags(o.flags());
763                     } else {
764                         __builtin_trap();
765                     }
766                 }
767             }
768             return *this;
769         }
770 
771         /**
772          * Copy constructor.
773          */
774         Custom(const Custom &o) : Custom() {
775             *this = o;
776         }
777 
778         /**
779          * Move assignment operator.
780          */
781         Custom& operator=(Custom &&o) noexcept {
782             if (&o != this) {
783                 if (this->used() && !this->clear()) {
784                     __builtin_trap();
785                 }
786                 if (o.used()) {
787                     if (_AData_move_assigner<Flagger, data_t, Ts...>::assign(
788                             o.flags(), this->get(), o.get())) {
789                         this->setFlags(o.flags());
790                         o.clear();
791                     } else {
792                         __builtin_trap();
793                     }
794                 }
795             }
796             return *this;
797         }
798 
799         /**
800          * Move constructor.
801          */
802         Custom(Custom &&o) noexcept : Custom() {
803             *this = std::move(o);
804         }
805 
806         /**
807          * Removes the contained object, if any.
808          */
809         ~Custom() {
810             if (!this->clear()) {
811                 __builtin_trap();
812                 // std::cerr << "could not delete data of type " << this->flags() << std::endl;
813             }
814         }
815 
816         /**
817          * Returns whether there is any object contained.
818          */
819         inline bool used() const {
820             return this->flags() != Flagger::flagFor((void*)0);
821         }
822 
823         /**
824          * Removes the contained object, if any. Returns true if there are no objects contained,
825          * or false on any error (this is highly unexpected).
826          */
827         bool clear() {
828             if (this->used()) {
829                 if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) {
830                     this->setFlags(Flagger::flagFor((void*)0));
831                     return true;
832                 }
833                 return false;
834             }
835             return true;
836         }
837 
838         template<typename T>
839         using is_supported_by_flagger =
840             typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type;
841 
842         /**
843          * Checks if there is a copiable object of type T in this container. If there is, it copies
844          * that object into the provided address and returns true. Otherwise, it does nothing and
845          * returns false.
846          *
847          * This method normally requires a flag equality between the stored and retrieved types.
848          * However, it also allows retrieving the stored object as the stored type
849          * (usually base type).
850          *
851          * \param T type of object to sought
852          * \param data address at which the object should be retrieved
853          *
854          * \return true if the object was retrieved. false if it was not.
855          */
856         template<
857                 typename T,
858                 typename=is_supported_by_flagger<T>>
859         bool find(T *data) const {
860             using B = typename Flagger::template store<T>::as_type;
861             if (this->flags() == Flagger::flagFor((T*)0) ||
862                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
863                 _AData_copier<T>::assign(data, this->get().template get<B>());
864                 return true;
865             }
866             return false;
867         }
868 
869         /**
870          * Checks if there is an object of type T in this container. If there is, it moves that
871          * object into the provided address and returns true. Otherwise, it does nothing and returns
872          * false.
873          *
874          * This method normally requires a flag equality between the stored and retrieved types.
875          * However, it also allows retrieving the stored object as the stored type
876          * (usually base type).
877          *
878          * \param T type of object to sought
879          * \param data address at which the object should be retrieved.
880          *
881          * \return true if the object was retrieved. false if it was not.
882          */
883         template<
884                 typename T,
885                 typename=is_supported_by_flagger<T>>
886         bool remove(T *data) {
887             using B = typename Flagger::template store<T>::as_type;
888             if (this->flags() == Flagger::flagFor((T*)0) ||
889                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
890                 _AData_mover<T>::assign(data, std::move(this->get().template get<B>()));
891                 return true;
892             }
893             return false;
894         }
895 
896         /**
897          * Stores an object into this container by copying. If it was successful, returns true.
898          * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This
899          * latter would be highly unexpected.
900          *
901          * \param T type of object to store
902          * \param data object to store
903          *
904          * \return true if the object was stored. false if it was not.
905          */
906         template<
907                 typename T,
908                 typename=is_supported_by_flagger<T>,
909                 typename=typename std::enable_if<
910                         std::is_copy_constructible<T>::value ||
911                         (std::is_default_constructible<T>::value &&
912                                 std::is_copy_assignable<T>::value)>::type>
913         bool set(const T &data) {
914             using B = typename Flagger::template store<T>::as_type;
915 
916             // if already contains an object of this type, simply assign
917             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
918                 _AData_copier<B>::assign(&this->get().template get<B>(), data);
919                 return true;
920             } else if (this->used()) {
921                 // destroy previous object
922                 if (!this->clear()) {
923                     return false;
924                 }
925             }
926             this->get().template emplace<B>(data);
927             this->setFlags(Flagger::flagFor((T *)0));
928             return true;
929         }
930 
931         /**
932          * Moves an object into this container. If it was successful, returns true. Otherwise,
933          * (e.g. it could not destroy the already stored object) it returns false. This latter
934          * would be highly unexpected.
935          *
936          * \param T type of object to store
937          * \param data object to store
938          *
939          * \return true if the object was stored. false if it was not.
940          */
941         template<
942                 typename T,
943                 typename=is_supported_by_flagger<T>>
944         bool set(T &&data) {
945             using B = typename Flagger::template store<T>::as_type;
946 
947             // if already contains an object of this type, simply assign
948             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
949                 _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data));
950                 return true;
951             } else if (this->used()) {
952                 // destroy previous object
953                 if (!this->clear()) {
954                     return false;
955                 }
956             }
957             this->get().template emplace<B>(std::forward<T&&>(data));
958             this->setFlags(Flagger::flagFor((T *)0));
959             return true;
960         }
961     };
962 
963     /**
964      * Basic AData using the default type flagger and requested flag type.
965      *
966      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
967      */
968     template<typename Flag>
969     using Strict = Custom<flagger<Flag>>;
970 
971     /**
972      * Basic AData using the default type flagger and uint32_t flag.
973      */
974     using Basic = Strict<uint32_t>;
975 
976     /**
977      * AData using the relaxed type flagger for max size and requested flag type.
978      *
979      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
980      */
981     template<typename Flag, size_t MaxSize = 1024, size_t Align = 4>
982     using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>;
983 
984     /**
985      * Basic AData using the relaxed type flagger and uint32_t flag.
986      */
987     using RelaxedBasic = Relaxed<uint32_t>;
988 };
989 
990 }  // namespace android
991 
992 #endif  // STAGEFRIGHT_FOUNDATION_A_DATA_H_
993 
994