| /* | |
| * Copyright (C) 2006 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. | |
| */ | |
| #ifndef ANDROID_USB_API_ADB_OBJECT_HANDLE_H__ | |
| #define ANDROID_USB_API_ADB_OBJECT_HANDLE_H__ | |
| /** \file | |
| This file consists of declaration of a class AdbObjectHandle that | |
| encapsulates an internal API object that is visible to the outside | |
| of the API through a handle. | |
| */ | |
| #include "adb_api.h" | |
| #include "adb_api_private_defines.h" | |
| /** \brief Defines types of internal API objects | |
| */ | |
| enum AdbObjectType { | |
| /// Object is AdbInterfaceEnumObject. | |
| AdbObjectTypeInterfaceEnumerator, | |
| /// Object is AdbInterfaceObject. | |
| AdbObjectTypeInterface, | |
| /// Object is AdbEndpointObject. | |
| AdbObjectTypeEndpoint, | |
| /// Object is AdbIOCompletion. | |
| AdbObjectTypeIoCompletion, | |
| AdbObjectTypeMax | |
| }; | |
| /** \brief Encapsulates an internal API basic object that is visible to the | |
| outside of the API through a handle. | |
| In order to prevent crashes when API client tries to access an object through | |
| an invalid or already closed handle, we keep track of all opened handles in | |
| AdbObjectHandleMap that maps association between valid ADBAPIHANDLE and | |
| an object that this handle represents. All objects that are exposed to the | |
| outside of API via ADBAPIHANDLE are self-destructing referenced objects. | |
| The reference model for these objects is as such: | |
| 1. When CreateHandle() method is called on an object, a handle (ADBAPIHANDLE | |
| that is) is assigned to it, a pair <handle, object> is added to the global | |
| AdbObjectHandleMap instance, object is referenced and then handle is | |
| returned to the API client. | |
| 2. Every time API is called with a handle, a lookup is performed in | |
| AdbObjectHandleMap to find an object that is associated with the handle. | |
| If object is not found then ERROR_INVALID_HANDLE is immediatelly returned | |
| (via SetLastError() call). If object is found then it is referenced and | |
| API call is dispatched to appropriate method of the found object. Upon | |
| return from this method, just before returning from the API call, object | |
| is dereferenced back to match lookup reference. | |
| 3. When object handle gets closed, assuming object is found in the map, that | |
| <handle, object> pair is deleted from the map and object's refcount is | |
| decremented to match refcount increment performed when object has been | |
| added to the map. | |
| 4. When object's refcount drops to zero, the object commits suicide by | |
| calling "delete this". | |
| All API objects that have handles that are sent back to API client must be | |
| derived from this class. | |
| */ | |
| class ADBWIN_API_CLASS AdbObjectHandle { | |
| public: | |
| /** \brief Constructs the object | |
| Refernce counter is set to 1 in the constructor. | |
| @param[in] obj_type Object type from AdbObjectType enum | |
| */ | |
| explicit AdbObjectHandle(AdbObjectType obj_type); | |
| protected: | |
| /** \brief Destructs the object. | |
| We hide destructor in order to prevent ourseves from accidentaly allocating | |
| instances on the stack. If such attempt occurs, compiler will error. | |
| */ | |
| virtual ~AdbObjectHandle(); | |
| public: | |
| /** \brief References the object. | |
| @return Value of the reference counter after object is referenced in this | |
| method. | |
| */ | |
| virtual LONG AddRef(); | |
| /** \brief Releases the object. | |
| If refcount drops to zero as the result of this release, the object is | |
| destroyed in this method. As a general rule, objects must not be touched | |
| after this method returns even if returned value is not zero. | |
| @return Value of the reference counter after object is released in this | |
| method. | |
| */ | |
| virtual LONG Release(); | |
| /** \brief Creates handle to this object. | |
| In this call a handle for this object is generated and object is added | |
| to the AdbObjectHandleMap. | |
| @return A handle to this object on success or NULL on an error. | |
| If NULL is returned GetLastError() provides extended error | |
| information. ERROR_GEN_FAILURE is set if an attempt was | |
| made to create already opened object. | |
| */ | |
| virtual ADBAPIHANDLE CreateHandle(); | |
| /** \brief This method is called when handle to this object gets closed. | |
| In this call object is deleted from the AdbObjectHandleMap. | |
| @return true on success or false if object is already closed. If | |
| false is returned GetLastError() provides extended error | |
| information. | |
| */ | |
| virtual bool CloseHandle(); | |
| /** \brief Checks if this object is of the given type. | |
| @param[in] obj_type One of the AdbObjectType types to check | |
| @return true is this object type matches obj_type, or false otherwise. | |
| */ | |
| virtual bool IsObjectOfType(AdbObjectType obj_type) const; | |
| /** \brief Looks up AdbObjectHandle instance associated with the given handle | |
| in the AdbObjectHandleMap. | |
| This method increments reference counter for the returned found object. | |
| @param[in] adb_handle ADB handle to the object | |
| @return API object associated with the handle or NULL if object is not | |
| found. If NULL is returned GetLastError() provides extended error | |
| information. | |
| */ | |
| static AdbObjectHandle* Lookup(ADBAPIHANDLE adb_handle); | |
| protected: | |
| /** \brief Called when last reference to this object is released. | |
| Derived object should override this method to perform cleanup that is not | |
| suitable for destructors. | |
| */ | |
| virtual void LastReferenceReleased(); | |
| public: | |
| /// Gets ADB handle associated with this object | |
| ADBAPIHANDLE adb_handle() const { | |
| return adb_handle_; | |
| } | |
| /// Gets type of this object | |
| AdbObjectType object_type() const { | |
| return object_type_; | |
| } | |
| /// Checks if object is still opened. Note that it is not guaranteed that | |
| /// object remains opened when this method returns. | |
| bool IsOpened() const { | |
| return (NULL != adb_handle()); | |
| } | |
| protected: | |
| /// API handle associated with this object | |
| ADBAPIHANDLE adb_handle_; | |
| /// Type of this object | |
| AdbObjectType object_type_; | |
| /// This object's reference counter | |
| LONG ref_count_; | |
| }; | |
| /// Maps ADBAPIHANDLE to associated AdbObjectHandle object | |
| typedef std::map< ADBAPIHANDLE, AdbObjectHandle* > AdbObjectHandleMap; | |
| /** \brief Template routine that unifies extracting of objects of different | |
| types from the AdbObjectHandleMap | |
| @param[in] adb_handle API handle for the object | |
| @return Object associated with the handle or NULL on error. If NULL is | |
| returned GetLastError() provides extended error information. | |
| */ | |
| template<class obj_class> | |
| obj_class* LookupObject(ADBAPIHANDLE adb_handle) { | |
| // Lookup object for the handle in the map | |
| AdbObjectHandle* adb_object = AdbObjectHandle::Lookup(adb_handle); | |
| if (NULL != adb_object) { | |
| // Make sure it's of the correct type | |
| if (!adb_object->IsObjectOfType(obj_class::Type())) { | |
| adb_object->Release(); | |
| adb_object = NULL; | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| } else { | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| return (adb_object != NULL) ? reinterpret_cast<obj_class*>(adb_object) : | |
| NULL; | |
| } | |
| #endif // ANDROID_USB_API_ADB_OBJECT_HANDLE_H__ |