localconnectivityservice/locod/src/locodserviceman.cpp
author hgs
Fri, 15 Oct 2010 15:05:57 +0800
changeset 54 4dc88a4ac6f4
parent 29 3ae5cb0b4c02
permissions -rw-r--r--
201041_02
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
29
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     1
/*
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     2
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     3
* All rights reserved.
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     4
* This component and the accompanying materials are made available
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     5
* under the terms of "Eclipse Public License v1.0"
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     6
* which accompanies this distribution, and is available
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     8
*
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
     9
* Initial Contributors:
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    10
* Nokia Corporation - initial contribution.
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    11
*
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    12
* Contributors:
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    13
*
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    14
* Description:  Daemon class implementation.
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    15
*
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    16
*/
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    17
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    18
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    19
#include <featmgr.h> 
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    20
#include <locodplugin.hrh>
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    21
#include <locodserviceplugin.h>
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    22
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    23
#include "locodserviceman.h"
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    24
#include "locodservice.h"
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    25
#include "debug.h"
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    26
#include "utils.h"
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    27
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    28
// ======== MEMBER FUNCTIONS ========
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    29
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    30
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    31
// NewL
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    32
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    33
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    34
CLocodServiceMan* CLocodServiceMan::NewL()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    35
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    36
    CLocodServiceMan* self = new (ELeave) CLocodServiceMan();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    37
    CleanupStack::PushL(self);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    38
    self->ConstructL();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    39
    CleanupStack::Pop(self);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    40
    return self;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    41
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    42
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    43
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    44
// C++ destructor
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    45
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    46
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    47
CLocodServiceMan::~CLocodServiceMan()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    48
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    49
    Cancel();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    50
    iServices.ResetAndDestroy();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    51
    iServices.Close();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    52
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    53
    TRACE_FUNC
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    54
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    55
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    56
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    57
// CActive method, the request is only completed when there is no service
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    58
// to manage, so all the service plugins are destroyed
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    59
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    60
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    61
void CLocodServiceMan::RunL()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    62
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    63
    TRACE_FUNC_ENTRY
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    64
        if(iStatus ==KErrNone)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    65
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    66
        iServices.ResetAndDestroy();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    67
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    68
        TRACE_FUNC_EXIT
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    69
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    70
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    71
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    72
// CActive method
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    73
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    74
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    75
void CLocodServiceMan::DoCancel()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    76
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    77
    
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    78
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    79
  
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    80
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    81
// CActive method
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    82
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    83
//  
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    84
TInt CLocodServiceMan::RunError(TInt/* aReason */)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    85
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    86
    return KErrNone;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    87
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    88
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    89
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    90
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    91
// NotifyBearerStatus
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    92
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    93
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    94
void CLocodServiceMan::NotifyBearerStatus(TLocodBearer aBearer, TBool aStatus)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    95
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    96
    TRACE_INFO((_L(" [BRRST] status of 0x%04x changes to %d"), aBearer, aStatus))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    97
    TInt oldStatus = iBearerStatus;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    98
    if (aStatus)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
    99
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   100
        iBearerStatus |= aBearer;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   101
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   102
    else
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   103
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   104
        iBearerStatus &= (~aBearer);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   105
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   106
    TRACE_INFO((_L(" [BRRST] [OLD] 0x%08x [NEW] 0x%08x"), oldStatus, iBearerStatus))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   107
    if (iBearerStatus && !iServices.Count())
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   108
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   109
        TRAP_IGNORE(LoadServicesL());
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   110
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   111
    TInt count = iServices.Count();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   112
    for (TInt i = 0; i < count; i++)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   113
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   114
        if(iBearerStatus != oldStatus)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   115
	        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   116
            iServices[i]->ManageService(aBearer, aStatus);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   117
	        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   118
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   119
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   120
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   121
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   122
// Call back method from service plugins. This is called when the services has been 
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   123
// managed by the plug ins.
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   124
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   125
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   126
void CLocodServiceMan::ManageServiceCompleted(TLocodBearer aBearer, 
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   127
    TBool aStatus, TUid aServiceImplUid, TInt err)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   128
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   129
    TInt count = iServices.Count();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   130
    for (TInt i = 0; i < count; i++)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   131
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   132
        if (iServices[i]->Plugin().ImplementationUid() == aServiceImplUid)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   133
            {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   134
            iServices[i]->ManageServiceCompleted(aBearer, aStatus, err);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   135
            break;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   136
            }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   137
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   138
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   139
    if (!iBearerStatus)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   140
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   141
        for (TInt i = 0; i < count; i++)
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   142
            {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   143
            if (iServices[i]->HasServiceToManage())
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   144
                {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   145
                return;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   146
                }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   147
            }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   148
    
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   149
        if(!IsActive())
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   150
        {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   151
            iStatus = KRequestPending;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   152
            SetActive();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   153
            TRequestStatus* status = &iStatus;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   154
            User::RequestComplete(status, KErrNone);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   155
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   156
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   157
        }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   158
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   159
  
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   160
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   161
// c++ constructor
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   162
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   163
//          
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   164
CLocodServiceMan::CLocodServiceMan() : CActive(CActive::EPriorityStandard),iUidDun(TUid::Uid(KFeatureIdDialupNetworking))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   165
    {        
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   166
    CActiveScheduler::Add(this);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   167
    TRACE_FUNC_THIS
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   168
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   169
  
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   170
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   171
// 2nd phase construction
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   172
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   173
//  
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   174
void CLocodServiceMan::ConstructL()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   175
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   176
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   177
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   178
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   179
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   180
// Loaded all service plug ins who has implemented the KLOCODSERVICEINTERFACEUID
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   181
// ---------------------------------------------------------------------------
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   182
//
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   183
void CLocodServiceMan::LoadServicesL()
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   184
    {
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   185
    TRACE_FUNC_ENTRY
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   186
    TRACE_INFO((_L("Load interface 0x%08X"), KLOCODSERVICEINTERFACEUID))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   187
	const TUid KServicePluginInterface = TUid::Uid(KLOCODSERVICEINTERFACEUID);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   188
	RImplInfoPtrArray implementations;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   189
	const TEComResolverParams noResolverParams;
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   190
	REComSession::ListImplementationsL(KServicePluginInterface, 
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   191
		noResolverParams,
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   192
		KRomOnlyResolverUid,
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   193
		implementations);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   194
	CleanupResetDestroyClosePushL(implementations);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   195
	const TUint count = implementations.Count();
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   196
    TRACE_INFO((_L(" [BRRST] Service Plug in found %d"), count))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   197
	for ( TUint ii = 0 ; ii < count ; ++ii )
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   198
		{
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   199
		CImplementationInformation* impl = implementations[ii];
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   200
		TRACE_INFO((_L("Service: feature %d, name '%S', ROM only %d"), 
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   201
		    impl->ImplementationUid().iUid, &(impl->DisplayName()), impl->RomOnly()))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   202
    	if (FeatureManager::FeatureSupported(impl->ImplementationUid().iUid))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   203
    		{
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   204
    		TRACE_INFO((_L("Feature found")))
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   205
            TLocodServicePluginParams params(impl->ImplementationUid(), *this);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   206
    		CLocodServicePlugin* srvcplugin = CLocodServicePlugin::NewL(params);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   207
    		CleanupStack::PushL(srvcplugin);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   208
    		CLocodService* service = CLocodService::NewL(*srvcplugin);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   209
    		CleanupStack::Pop(srvcplugin);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   210
    		CleanupStack::PushL(service);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   211
    		iServices.AppendL(service);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   212
    		CleanupStack::Pop(service);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   213
    		}
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   214
		}
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   215
	CleanupStack::PopAndDestroy(&implementations);
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   216
    TRACE_FUNC_EXIT    
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   217
    }
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   218
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   219
3ae5cb0b4c02 201025_07
hgs
parents:
diff changeset
   220