Table of Contents

Target Platform(s):

include/AK/Tools/Android/AkPlatformFuncs.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
00003 released in source code form as part of the SDK installer package.
00004 
00005 Commercial License Usage
00006 
00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
00008 may use this file in accordance with the end user license agreement provided 
00009 with the software or, alternatively, in accordance with the terms contained in a
00010 written agreement between you and Audiokinetic Inc.
00011 
00012 Apache License Usage
00013 
00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 
00015 "Apache License"); you may not use this file except in compliance with the 
00016 Apache License. You may obtain a copy of the Apache License at 
00017 http://www.apache.org/licenses/LICENSE-2.0.
00018 
00019 Unless required by applicable law or agreed to in writing, software distributed
00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
00022 the specific language governing permissions and limitations under the License.
00023 
00024   Version: <VERSION>  Build: <BUILDNUMBER>
00025   Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
00026 *******************************************************************************/
00027 
00028 #pragma once
00029 
00030 #include <AK/Tools/Common/AkAssert.h>
00031 #include <AK/SoundEngine/Common/AkTypes.h>
00032 #include <android/log.h>
00033 
00034 #include <time.h>
00035 #include <stdlib.h>
00036 
00037 #define AK_THREAD_INIT_CODE(_threadProperties) syscall(__NR_sched_setaffinity, 0, sizeof(_threadProperties.dwAffinityMask), &_threadProperties.dwAffinityMask)
00038 
00039 
00040 namespace AKPLATFORM
00041 {
00042     /// Platform Independent Helper
00043     inline void PerformanceFrequency( AkInt64 * out_piFreq )
00044     {
00045         // TO DO ANDROID ... is there something better
00046         *out_piFreq = CLOCKS_PER_SEC;
00047     }
00048 }
00049 
00050 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
00051 
00052 namespace AKPLATFORM
00053 {
00054 
00055 #ifndef AK_OPTIMIZED
00056     /// Output a debug message on the console (Ansi string)
00057     inline void OutputDebugMsg( const char* in_pszMsg )
00058     {
00059         // To see output of this 
00060         // adb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S
00061         __android_log_print(ANDROID_LOG_INFO, "AKDEBUG", "%s", in_pszMsg);  
00062     }   
00063 #else   
00064     inline void OutputDebugMsg( const char* ){}
00065 #endif
00066     // Atomic Operations
00067     // ------------------------------------------------------------------
00068 
00069     /// Platform Independent Helper
00070     inline AkInt32 AkInterlockedIncrement( AkAtomic32 * pValue )
00071     {
00072         return __atomic_add_fetch(pValue,1, __ATOMIC_SEQ_CST);
00073     }
00074 
00075     /// Platform Independent Helper
00076     inline AkInt32 AkInterlockedDecrement( AkAtomic32 * pValue )
00077     {
00078         return __atomic_sub_fetch(pValue,1, __ATOMIC_SEQ_CST);
00079     }
00080 
00081     inline bool AkInterlockedCompareExchange( volatile AkAtomic32* io_pDest, AkInt32 in_newValue, AkInt32 in_expectedOldVal )
00082     {
00083         return __atomic_compare_exchange(io_pDest, &in_expectedOldVal, &in_newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
00084     }
00085     
00086     inline bool AkInterlockedCompareExchange( volatile AkAtomic64* io_pDest, AkInt64 in_newValue, AkInt64 in_expectedOldVal)
00087     {
00088         return __atomic_compare_exchange(io_pDest, &in_expectedOldVal, &in_newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
00089     }
00090 
00091     inline void AkMemoryBarrier()
00092     {
00093          __atomic_thread_fence(__ATOMIC_SEQ_CST);
00094          /*
00095 #ifdef AK_CPU_ARM
00096         __asm("DMB ST");    //Wait for stores to complete.
00097 #elif AK_CPU_X86
00098         __asm("mfence");    
00099 #endif*/
00100     }
00101 
00102     // Time functions
00103     // ------------------------------------------------------------------
00104 
00105     /// Platform Independent Helper
00106     inline void PerformanceCounter( AkInt64 * out_piLastTime )
00107     {
00108         *out_piLastTime = clock();
00109     }
00110     
00111 
00112     template<class destType, class srcType>
00113     inline size_t AkSimpleConvertString( destType* in_pdDest, const srcType* in_pSrc, size_t in_MaxSize, size_t destStrLen(const destType *),  size_t srcStrLen(const srcType *) )
00114     { 
00115         size_t i;
00116         size_t lenToCopy = srcStrLen(in_pSrc);
00117         
00118         lenToCopy = (lenToCopy > in_MaxSize-1) ? in_MaxSize-1 : lenToCopy;
00119         for(i = 0; i < lenToCopy; i++)
00120         {
00121             in_pdDest[i] = (destType) in_pSrc[i];
00122         }
00123         in_pdDest[lenToCopy] = (destType)0;
00124         
00125         return lenToCopy;
00126     }
00127 
00128     #define CONVERT_UTF16_TO_CHAR( _astring_, _charstring_ ) \
00129         _charstring_ = (char*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(char) ); \
00130         AK_UTF16_TO_CHAR( _charstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 ) 
00131 
00132     #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkSimpleConvertString(  in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
00133     #define AK_UTF16_TO_CHAR(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkSimpleConvertString(  in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
00134     #define AK_CHAR_TO_UTF16(   in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkSimpleConvertString(  in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)  
00135     #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize )    AKPLATFORM::AkSimpleConvertString(  in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)  
00136     
00137     /// Stack allocations.
00138     #define AkAlloca( _size_ ) __builtin_alloca( _size_ )
00139 
00140     #if __BIGGEST_ALIGNMENT__ < AK_SIMD_ALIGNMENT
00141     #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, AK_SIMD_ALIGNMENT*8 )
00142     #endif
00143 
00144     /// Platform Independent Helper
00145     inline void AkCreateThread( 
00146         AkThreadRoutine pStartRoutine,                  // Thread routine.
00147         void * pParams,                                 // Routine params.
00148         const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
00149         AkThread * out_pThread,                         // Returned thread handle.
00150         const char * /*in_szThreadName*/ )              // Opt thread name.
00151     {
00152         AKASSERT( out_pThread != NULL );
00153 
00154         pthread_attr_t  attr;
00155 
00156         // Create the attr
00157         AKVERIFY(!pthread_attr_init(&attr));
00158         // Set the stack size
00159         AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize));
00160 
00161         AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));     
00162 
00163         // Create the tread
00164         int     threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams);
00165         AKASSERT( threadError == 0 );
00166         AKVERIFY(!pthread_attr_destroy(&attr));
00167 
00168         if( threadError != 0 )
00169         {
00170             AkClearThread( out_pThread );
00171             return;
00172         }
00173 
00174         // ::CreateThread() return NULL if it fails.
00175         if ( !*out_pThread )
00176         {
00177             AkClearThread( out_pThread );
00178             return;
00179         }       
00180 
00181         // Try to set the thread policy
00182         int sched_policy = in_threadProperties.uSchedPolicy;        
00183 
00184         // Get the priority for the policy
00185         int minPriority, maxPriority;
00186         minPriority = sched_get_priority_min(sched_policy);
00187         maxPriority = sched_get_priority_max(sched_policy);
00188 
00189         // Set the thread priority if valid
00190         sched_param schedParam;
00191         schedParam.sched_priority = in_threadProperties.nPriority;  
00192         AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );       
00193 
00194         //pthread_setschedparam WILL fail on Android Lollipop when used with SCHED_FIFO (the default).  Not allowed anymore. (ignore the error code).
00195         int err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
00196         if (err != 0)
00197         {           
00198             //Make sure the priority is well set, even if the policy could not.         
00199             sched_policy = SCHED_NORMAL;
00200             minPriority = sched_get_priority_min(sched_policy);
00201             maxPriority = sched_get_priority_max(sched_policy);
00202             if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_ABOVE_NORMAL)
00203                 schedParam.sched_priority = maxPriority;
00204             else if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_BELOW_NORMAL)
00205                 schedParam.sched_priority = minPriority;
00206             else
00207                 schedParam.sched_priority = (maxPriority + minPriority) / 2;
00208             err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);                       
00209             AKASSERT(err == 0);
00210         }
00211     }
00212 }