/*static*/
String CRingtoneManager::ConstructBooleanTrueWhereClause(
    /* [in] */ List<String>* columns,
    /* [in] */ Boolean includeDrm)
{
    String tempNull;
    if (columns == NULL) {
        return tempNull;
    }

    StringBuilder sb;
    sb += "(";

    for (Int32 i = columns->GetSize() - 1; i >= 0; i--) {
        sb += (*columns)[i];
        sb += "=1 or ";
    }

    if (columns->IsEmpty() == FALSE) {
        // Remove last ' or '
        Int32 tempValue;
        sb.GetLength(&tempValue);
        String tempText;
        sb.Substring(tempValue - 4, &tempText);
        sb.Reset();
        sb += tempText;
    }

    sb += ")";

    if (!includeDrm) {
        // If not DRM files should be shown, the where clause
        // will be something like "(is_notification=1) and is_drm=0"
        sb += " and ";
        sb += IMediaStoreMediaColumns::IS_DRM;
        sb += "=0";
    }
    String tempText;
    sb.ToString(&tempText);
    return tempText;
}
void RegisteredServicesCache::GenerateServicesMap(
    /* [in] */ Int32 userId)
{
    Slogger::D(TAG, "generateServicesMap() for %d", userId);

    AutoPtr<IPackageManager> pm;
    mContext->GetPackageManager((IPackageManager**)&pm);
    List<AutoPtr<IRegisteredServicesCacheServiceInfo> > serviceInfos;
    AutoPtr<IList> resolveInfos;
    AutoPtr<IIntent> intent;
    CIntent::New(mInterfaceName, (IIntent**)&intent);
    ASSERT_SUCCEEDED(pm->QueryIntentServicesAsUser(intent, IPackageManager::GET_META_DATA, userId,
            (IList**)&resolveInfos));
    AutoPtr<IIterator> it;
    resolveInfos->GetIterator((IIterator**)&it);
    Boolean hasNext;
    while (it->HasNext(&hasNext), hasNext) {
        AutoPtr<IInterface> current;
        it->GetNext((IInterface**)&current);
        AutoPtr<IResolveInfo> resolveInfo = IResolveInfo::Probe(current);
        // try {
        AutoPtr<IRegisteredServicesCacheServiceInfo> info;
        ECode ec = ParseServiceInfo(resolveInfo, (IRegisteredServicesCacheServiceInfo**)&info);
        if (FAILED(ec)) {
            String s;
            resolveInfo->ToString(&s);
            Slogger::W(TAG, "Unable to load service info %s ec = 0x%08x", s.string(), ec);
            continue;
        }
        serviceInfos.PushBack(info);
        // } catch (XmlPullParserException e) {
        //     Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
        // } catch (IOException e) {
        //     Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
        // }
    }

    AutoLock lock(mServicesLock);

    AutoPtr<UserServices> user = FindOrCreateUserLocked(userId);
    Boolean firstScan = user->mServices == NULL;
    if (firstScan) {
        user->mServices = new HashMap<AutoPtr<IInterface>, AutoPtr<IRegisteredServicesCacheServiceInfo> >();
    }
    else {
        user->mServices->Clear();
    }

    StringBuilder changes;
    Boolean changed = FALSE;
    ServiceInfo* info;
    List<AutoPtr<IRegisteredServicesCacheServiceInfo> >::Iterator itr = serviceInfos.Begin();
    for (Int32 i = 0; itr != serviceInfos.End(); ++itr, ++i) {
        info = (ServiceInfo*)(*itr).Get();
        // four cases:
        // - doesn't exist yet
        //   - add, notify user that it was added
        // - exists and the UID is the same
        //   - replace, don't notify user
        // - exists, the UID is different, and the new one is not a system package
        //   - ignore
        // - exists, the UID is different, and the new one is a system package
        //   - add, notify user that it was added
        AutoPtr<IInteger32> previousUid;
        HashMap<AutoPtr<IInterface>, AutoPtr<IInteger32> >::Iterator it = user->mPersistentServices.Find(info->mType);
        if (it != user->mPersistentServices.End()) {
            previousUid = it->mSecond;
        }
        if (previousUid == NULL) {
            if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
                changes += "  New service added: ";
                changes += Object::ToString(info);
                changes += "\n";
            }

            changed = TRUE;
            (*user->mServices)[info->mType] = info;
            AutoPtr<IInteger32> iuid;
            CInteger32::New(info->mUid, (IInteger32**)&iuid);
            (user->mPersistentServices)[info->mType] = iuid;
            if (!(mPersistentServicesFileDidNotExist && firstScan)) {
                NotifyListener(info->mType, userId, FALSE /* removed */);
            }
        }
        else {
            Int32 pUid;
            previousUid->GetValue(&pUid);
            if (pUid == info->mUid) {
                if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
                    changes += "  Existing service (nop): ";
                    changes += Object::ToString(info);
                    changes += "\n";
                }
                (*user->mServices)[info->mType] = info;
            }
            else if (InSystemImage(info->mUid)
                    || !ContainsTypeAndUid(&serviceInfos, info->mType, pUid)) {
                if (InSystemImage(info->mUid)) {
                    if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
                        changes += ("  System service replacing existing: ");
                        changes += Object::ToString(info);
                        changes += ("\n");
                    }
                }
                else {
                    if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
                        changes += ("  Existing service replacing a removed service: ");
                        changes += Object::ToString(info);
                        changes += ("\n");
                    }
                }
                (*user->mServices)[info->mType] = info;
                AutoPtr<IInteger32> iuid;
                CInteger32::New(info->mUid, (IInteger32**)&iuid);
                (user->mPersistentServices)[info->mType] = iuid;
                NotifyListener(info->mType, userId, FALSE /* removed */);
            }
            else {
                if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
                    // ignore
                    changes += ("  Existing service with new uid ignored: ");
                    changes += Object::ToString(info);
                    changes += ("\n");
                }
            }
        }
    }

    List<AutoPtr<IInterface> > toBeRemoved;
    HashMap<AutoPtr<IInterface>, AutoPtr<IInteger32> >::Iterator item = user->mPersistentServices.Begin();
    for (; item != user->mPersistentServices.End(); ++item) {
        AutoPtr<IInterface> v1 = item->mFirst;
        if (!ContainsType(&serviceInfos, v1)) {
            toBeRemoved.PushBack(v1);
        }
    }
    List<AutoPtr<IInterface> >::Iterator toBeRemItr = toBeRemoved.Begin();
    for (; toBeRemItr != toBeRemoved.End(); ++toBeRemItr) {
        AutoPtr<IInterface> v1 = *toBeRemItr;
        user->mPersistentServices.Erase(v1);
        NotifyListener(v1, userId, TRUE /* removed */);
        changed = TRUE;

        if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
            changes += ("  Service removed: ");
            changes += Object::ToString(v1);
            changes += ("\n");
        }
    }

    if (Logger::IsLoggable(TAG, Logger::VERBOSE)) {
        if (changes.GetLength() > 0) {
            Logger::D(TAG, "generateServicesMap(%s): %d services:%s\n",
                    mInterfaceName.string(), serviceInfos.GetSize(), changes.ToString().string());
        }
        else {
            Logger::D(TAG, "generateServicesMap(%s): %d services unchanged",
                    mInterfaceName.string(), serviceInfos.GetSize());
        }
    }

    if (changed) {
        WritePersistentServicesLocked();
    }
}
	// ------------------------------------------------------------------------------------------
	//! Generates the HLSL shader Byte code.
	//! @param ShaderByteCodeOutputStream Output for the shader code.
	//! @param ShaderParsedData Parsed shader data, produced by @ref HLSLParser
	//! @param ShaderType Type of the shader to generate code.
	//! @param ShaderEntryName Name of the shader entry point.
	//! @param ShaderTargetPlatform Target platform for the GLSL code.
	void GLSLCompiler::GenerateAndCompileShader(UniquePtr<OutputStream> const& ShaderByteCodeOutputStream
		, HLSLScope const* const ShaderParsedData, IGraphicsShaderType const ShaderType, String const& ShaderEntryName
		, DHLSLShaderCrossCompilerTarget const ShaderTargetPlatform)
	{
		StringBuilder GLSLGeneratorBuilder;
		GLSLGenerator().GenerateShader(GLSLGeneratorBuilder, ShaderParsedData, ShaderEntryName, ShaderTargetPlatform, ShaderType);

		// Now we need just preprocess generated code to reduce loading time.
		StringBuilder GLSLPreprocessedBuilder;
		GLSLPreprocessedBuilder.Append(GLSLInsertations::GLSLCopyright);
		GLSLPreprocessedBuilder.Append(GLSLInsertations::GLSLPreambule[ShaderTargetPlatform - DHLSL_CC_TARGET_GLSL430]);

		// We use MCPP preprocessor because it is faster than our one.
		//! @todo Implement temporary files access here.
		String const MCPPSourceFilePath = "a.tmp";// Path::GetTemporaryFileName();
		String const MCPPOutputFilePath = "b.tmp";// Path::GetTemporaryFileName();
		CStr   const MCPPArguments[] = { nullptr, "-P", MCPPSourceFilePath.CStr(), MCPPOutputFilePath.CStr() };

		// Saving output to some temporary file to make is accessible from MCPP
		FileOutputStream MCPPSourceFile(/*MCPPSourceFilePath*/L"a.tmp");
		MCPPSourceFile.Write(GLSLGeneratorBuilder.CStr(), GLSLGeneratorBuilder.GetLength(), sizeof(Char));
		MCPPSourceFile.Close();

		{ 
		//	MCPP is not thread-safe.
		//	CriticalSection static MCPPCriticalSection;
		//	ScopedCriticalSection MCPPLock(MCPPCriticalSection);
			int const MCPPResult = mcpp_lib_main(GD_ARRAY_LENGTH(MCPPArguments), const_cast<char**>(&MCPPArguments[0]));
			GD_DEBUG_ASSERT(MCPPResult == 0, "Failed to preprocess shader source.");
		}
		// Reading MCPP result.
		{
			FileInputStream MCPPOutputFile(/*MCPPOutputFilePath*/L"b.tmp");
			SizeTp const GLSLPreprocessedBuilderPos = GLSLPreprocessedBuilder.GetLength();
			GLSLPreprocessedBuilder.Resize(GLSLPreprocessedBuilder.GetLength() + (UInt32) MCPPOutputFile.GetLength());
			MCPPOutputFile.Read(GLSLPreprocessedBuilder.CStr() + GLSLPreprocessedBuilderPos, MCPPOutputFile.GetLength(), 1);
			MCPPOutputFile.Close();
			GLSLPreprocessedBuilder.Append('\0');
			GD_DEBUG_ASSERT(::remove(MCPPSourceFilePath.CStr()) == 0, "Failed to remove mcpp source file.");
			GD_DEBUG_ASSERT(::remove(MCPPOutputFilePath.CStr()) == 0, "Failed to remove mcpp output file.");
		}

		// Trying to optimize the GLSL code..
		StringBuilder GLSLOptimizerBuilder;
		/**/if (ShaderTargetPlatform != DHLSL_CC_TARGET_GLSL430									// glsl_optimizer supports only desktop GLSL 140 version. We are using 430...			
			&& (ShaderType != IGRAPHICS_SHADER_TYPE_VERTEX && ShaderType != IGRAPHICS_SHADER_TYPE_PIXEL))	// glsl_optimizer supports only vertex and pixel shaders...
		{
			// Optimizing is supported for this shader type and target.
			glslopt_target static const IGraphicsGLSLangTargetsTable[] = {
				/* DHLSL_CC_TARGET_GLSL430 */ kGlslTargetOpenGL,
				/* DHLSL_CC_TARGET_GLSLES3 */ kGlslTargetOpenGLES20,
				/* DHLSL_CC_TARGET_GLSLES2 */ kGlslTargetOpenGLES30,
			};
			glslopt_shader_type static const IGraphicsGLSLangShaderTypesTable[] = {
				/* IGRAPHICS_SHADER_TYPE_VERTEX */ kGlslOptShaderVertex,
				/* IGRAPHICS_SHADER_TYPE_PIXEL  */ kGlslOptShaderFragment,
			};

			auto const OptimizerContext = glslopt_initialize(IGraphicsGLSLangTargetsTable[ShaderTargetPlatform]);
			auto const OptimizedShader = glslopt_optimize(OptimizerContext, IGraphicsGLSLangShaderTypesTable[ShaderType - DHLSL_CC_TARGET_GLSL430]
				, GLSLPreprocessedBuilder.CStr(), kGlslOptionSkipPreprocessor);
			if (!glslopt_get_status(OptimizedShader))
			{
				// Shader was not optimized..
				// This does not mean that our shader is incorrect, just MESA-based optimizer may not parse
#if 0			// our code correctly.
				CStr const ShaderOptimizationLog = glslopt_get_log(OptimizedShader);
				throw GLSLCompilerErrorException("shader optimization failed with following log: \n%s", ShaderOptimizationLog);
#endif	// if 0
				GLSLOptimizerBuilder = Move(GLSLPreprocessedBuilder);
			}
			else
			{
				// Shader was optimized..
				GLSLOptimizerBuilder.Append(glslopt_get_output(OptimizedShader));
			}

			glslopt_shader_delete(OptimizedShader);
			glslopt_cleanup(OptimizerContext);
		}
		else
		{
			// Shader was not optimized - using default version.
			GLSLOptimizerBuilder = Move(GLSLPreprocessedBuilder);
		}

		// No we need to validate our shader.. 
		TBuiltInResource static const GLSLangDefaultResources{ INT_MAX };
		EShLanguage static const IGraphicsGLSLangShaderTypesTable[IGRAPHICS_SHADER_TYPES_COUNT] = {
			/* IGRAPHICS_SHADER_TYPE_VERTEX   */ EShLangVertex,
			/* IGRAPHICS_SHADER_TYPE_PIXEL    */ EShLangFragment,
			/* IGRAPHICS_SHADER_TYPE_GEOMETRY */ EShLangGeometry,
			/* IGRAPHICS_SHADER_TYPE_HULL     */ EShLangTessControl,
			/* IGRAPHICS_SHADER_TYPE_DOMAIN   */ EShLangTessEvaluation,
			/* IGRAPHICS_SHADER_TYPE_COMPUTE  */ EShLangCompute,
			/* IGRAPHICS_SHADER_TYPE_UNKNOWN  */ EShLangCount,
		};

		glslang::InitializeProcess();

		// Trying to compile our shader..
		char const* const GLSLOptimizerBuilderPtr = GLSLOptimizerBuilder.CStr();
		glslang::TShader GLSLangShader(IGraphicsGLSLangShaderTypesTable[ShaderType]);
		GLSLangShader.setStrings(&GLSLOptimizerBuilderPtr, 1);
		if (!GLSLangShader.parse(&GLSLangDefaultResources, 100, true, EShMsgDefault))
		{ 
			// Failed to compile our shader.
			throw GLSLCompilerErrorException("GLSLang compilation returned errors: \n%s\nGenerated code:\n%s", GLSLangShader.getInfoLog(), GLSLOptimizerBuilderPtr);
		}
		else
		{
#if 0
			Debug::Log(GLSLangShader.getInfoLog());
#endif	// if 0
		}

		// Trying to link our shader program..
		glslang::TProgram GLSLangProgram;
		GLSLangProgram.addShader(&GLSLangShader);
		if (!GLSLangProgram.link(EShMsgDefault))
		{ 
			throw GLSLCompilerErrorException("GLSLang linking returned errors: \n%s", GLSLangProgram.getInfoLog());
		}
		else
		{
#if 0
			Debug::Log(GLSLangProgram.getInfoLog());
#endif	// if 0
		}

		glslang::FinalizeProcess();

		ShaderByteCodeOutputStream->Write(GLSLOptimizerBuilder.CStr(), GLSLOptimizerBuilder.GetLength(), sizeof(Char));
	}
	// ------------------------------------------------------------------------------------------
	//! @todo Document and cleanup me.
	void GLSLGenerator::GenerateShaderEntryPoint(HLSLFunction const* const EntryPoint, StringBuilder& Builder)
	{
		StringBuilder FakeEntryAssigment;
		StringBuilder FakeEntryInvocation;
		StringBuilder FakeEntryInternals, FakeEntryExternals;
		int LastUsedSemanticIn = 0, LastUsedSemanticOut = 0;
		for (auto const& Argument : EntryPoint->Arguments)
		{
			CStr const ArgumentAccessType = Argument->AccsessType == GD_HLSL_ARGUMENT_IN ? "in " : "out";
			int& LastUsedSemantic = Argument->AccsessType == GD_HLSL_ARGUMENT_IN ? LastUsedSemanticIn : LastUsedSemanticOut;

			if (Argument->Type->Class == GD_HLSL_TYPE_CLASS_STRUCT)
			{
				if (Argument->AccsessType == GD_HLSL_ARGUMENT_IN)
				{
					FakeEntryInvocation.AppendFormat("%s(", Argument->Type->Name.CStr(), Argument->Name.CStr());
				}
				else
				{
					FakeEntryInvocation.AppendFormat("%s, ", Argument->Name.CStr());
					FakeEntryInternals.AppendFormat("\n\t%s %s;", Argument->Type->Name.CStr(), Argument->Name.CStr());
				}

				auto const Struct = static_cast<HLSLStruct const*>(Argument->Type);
				for (auto const& Definition : Struct->InnerDefinitions)
				{
					auto const StructField = static_cast<HLSLVariable const*>(Definition);
				//	auto const StructFieldSemantic = static_cast<HLSLSemantic const*>(StructField->Binding);
					FakeEntryExternals.AppendFormat("\nlayout(location = %d) %s %s Varying%s%s;", LastUsedSemantic
						, ArgumentAccessType, StructField->Type->Name.CStr(), Argument->Name.CStr(), StructField->Name.CStr());

					if (Argument->AccsessType == GD_HLSL_ARGUMENT_IN)
						FakeEntryInvocation.AppendFormat("Varying%s%s, ", Argument->Name.CStr(), StructField->Name.CStr());
					else
						FakeEntryAssigment.AppendFormat("\n\tVarying%s%s = %s.%s;", Argument->Name.CStr(), StructField->Name.CStr(), Argument->Name.CStr(), StructField->Name.CStr());
					LastUsedSemantic += 1;
				}

				if (Argument->AccsessType == GD_HLSL_ARGUMENT_IN)
				{
					//! @todo Refactor this awful code.
					*(FakeEntryInvocation.CStr() + FakeEntryInvocation.GetLength() - 2) = ')'; // Removing trailing comma.
					*(FakeEntryInvocation.CStr() + FakeEntryInvocation.GetLength() - 1) = ','; // Removing trailing space.
					FakeEntryInvocation.Append(' ');
				}
			}
			else
			{
				auto const ArgumentSemantic = static_cast<HLSLSemantic const*>(Argument->Binding);
				if (Argument->AccsessType == GD_HLSL_ARGUMENT_OUT)
				{
					if (ArgumentSemantic->Semantic == GD_HLSL_SEMANTIC_SV_Position)
						FakeEntryAssigment.AppendFormat("\n\tgl_Position = %s;", Argument->Name.CStr());
				}

				FakeEntryExternals.AppendFormat("\nlayout(location = %d) %s %s Varying%s;", LastUsedSemantic, ArgumentAccessType, Argument->Type->Name.CStr(), Argument->Name.CStr());
				FakeEntryInvocation.AppendFormat("Varying%s, ", Argument->Name.CStr());

				LastUsedSemantic += 1;
			}
		}

		//! @todo Refactor this awful code.
		*(FakeEntryInvocation.CStr() + FakeEntryInvocation.GetLength() - 2) = ')'; // Removing trailing comma.
		*(FakeEntryInvocation.CStr() + FakeEntryInvocation.GetLength() - 1) = ';'; // Removing trailing space.
		FakeEntryInvocation = Move(StringBuilder().AppendFormat("\n\t%s(%s", EntryPoint->Name.CStr(), FakeEntryInvocation.CStr()));

		if (EntryPoint->Type->Class == GD_HLSL_TYPE_CLASS_STRUCT)
		{
			FakeEntryInternals.AppendFormat("\n\t%s Ret;", EntryPoint->Type->Name.CStr());
			FakeEntryInvocation = Move(StringBuilder().AppendFormat("\n\tRet = %s", FakeEntryInvocation.CStr() + 2));

			HLSLStruct const* const ReturnStruct = static_cast<HLSLStruct const*>(EntryPoint->Type);
			for (auto const& Definition : ReturnStruct->InnerDefinitions)
			{
				HLSLVariable const* const ReturnStructField = static_cast<HLSLVariable const*>(Definition);
			//	HLSLSemantic const* const ReturnStructFieldSemantic = static_cast<HLSLSemantic const*>(ReturnStructField->Binding);
				FakeEntryExternals.AppendFormat("\nlayout(location = %d) out %s VaryingRet%s;", LastUsedSemanticOut, ReturnStructField->Type->Name.CStr(), ReturnStructField->Name.CStr());
				FakeEntryAssigment.AppendFormat("\n\tVaryingRet%s = Ret.%s;", ReturnStructField->Name.CStr(), ReturnStructField->Name.CStr());
				LastUsedSemanticOut += 1;
			}
		}
		else if (EntryPoint->Semantic != nullptr)
		{
			FakeEntryExternals.AppendFormat("\nlayout(location = %d) out %s VaryingRet;", LastUsedSemanticOut, EntryPoint->Name.CStr());
			FakeEntryInvocation = Move(StringBuilder().AppendFormat("\n\tVaryingRet = %s", FakeEntryInvocation.CStr() + 2));
		}

		Builder.AppendFormat("\n%s\n\nvoid main()\n{\n%s\n%s\n%s}\n", FakeEntryExternals.CStr()
			, FakeEntryInternals.CStr(), FakeEntryInvocation.CStr(), FakeEntryAssigment.CStr());
	}