/*
* Tencent is pleased to support the open source community by making
* Tencent GT (Version 2.4 and subsequent versions) available.
*
* Notwithstanding anything to the contrary herein, any previous version
* of Tencent GT shall not be subject to the license hereunder.
* All right, title, and interest, including all intellectual property rights,
* in and to the previous version of Tencent GT (including any and all copies thereof)
* shall be owned and retained by Tencent and subject to the license under the
* Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html).
*
* Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* 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.
*/
package com.tencent.wstt.gt.client.internal;
import com.tencent.wstt.gt.Functions;
import com.tencent.wstt.gt.GTConfig;
import com.tencent.wstt.gt.IService;
import com.tencent.wstt.gt.client.AbsGTParaLoader;
import com.tencent.wstt.gt.client.GT;
import com.tencent.wstt.gt.client.GTConnectListener;
import com.tencent.wstt.gt.client.communicate.ComImpl;
import com.tencent.wstt.gt.client.communicate.ICom;
import com.tencent.wstt.gt.client.internal.connect.ConnectedState;
import com.tencent.wstt.gt.client.internal.connect.ConnectingState;
import com.tencent.wstt.gt.client.internal.connect.DisconnectingState;
import com.tencent.wstt.gt.client.internal.connect.IConnState;
import com.tencent.wstt.gt.client.internal.connect.NotConnectedState;
import com.tencent.wstt.gt.client.internal.connect.NotInstalledState;
import com.tencent.wstt.gt.data.control.DataCacheController;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
/**
* GT提供给宿主调用的总接口
*/
public class GTInternal {
public static GTInternal INSTANCE = new GTInternal();
public static GTInternal getInstance() {
return INSTANCE;
}
private Context context;
private IService gtService;
private ICom gtCom;
// 当前的数据缓存控制器,在Connecting和Connected两个状态才会调用其init方法
// 实际使用可能要传service给它
private DataCacheController dataCacheController;
// 尚未连接到GT控制台
IConnState CONNECT_STATE_NOT_CONNECTED;
// 连接到GT控制台中
IConnState CONNECT_STATE_CONNECTING;
// 本次连接时GT控制台尚未安装
IConnState CONNECT_STATE_NOT_INSTALLED;
// 正在主动与GT控制台断连中
IConnState CONNECT_STATE_DISCONNECTING;
// 已连接到GT控制台
IConnState CONNECT_STATE_CONNECTED;
// 当前连接状态
private IConnState curConnState;
private GTConnectListener gTConnectListener;
// 处理GT服务端应用状态通知的Handler
private SplashHandler splashHandler;
GTServiceConnection gtServiceConnection;
private InParaManagerInternal inParaManager;
private OutParaManagerInternal outParaManager;
public static String GT_PACKAGE_NAME = "com.tencent.wstt.gt";
public static final String ACTION = "com.tencent.wstt.gt.service";
public static String smPara;
public InParaManagerInternal getInParaManager()
{
return inParaManager;
}
public OutParaManagerInternal getOutParaManager()
{
return outParaManager;
}
private GTInternal() {
inParaManager = new InParaManagerInternal();
outParaManager = new OutParaManagerInternal();
dataCacheController = new DataCacheController();
CONNECT_STATE_NOT_CONNECTED = new NotConnectedState(dataCacheController);
CONNECT_STATE_CONNECTING = new ConnectingState(dataCacheController);
CONNECT_STATE_NOT_INSTALLED = new NotInstalledState(dataCacheController);
CONNECT_STATE_DISCONNECTING = new DisconnectingState(dataCacheController);
CONNECT_STATE_CONNECTED = new ConnectedState(dataCacheController);
curConnState = CONNECT_STATE_NOT_CONNECTED;
}
void setGTService(IService gtService) {
this.gtService = gtService;
}
public IService getGTService()
{
return gtService;
}
/**
* 当前是否可以尝试去连接GT
* @return
*/
public boolean isCanTryConnect()
{
if (curConnState == CONNECT_STATE_NOT_CONNECTED
|| curConnState == CONNECT_STATE_NOT_INSTALLED)
{
return true;
}
return false;
}
/**
* 加载GT主应用程序
*
* @param hostContext
* 宿主应用的Context
* @return 只有GT未安装会返回false
*/
public boolean connect(Context hostContext, AbsGTParaLoader loader) {
if (hostContext == null) return false;
Context app = hostContext.getApplicationContext();
if (isCanTryConnect())
{
setHostContext(app);
setConnState(CONNECT_STATE_CONNECTING);
// 获取GT应用Context的一个镜像对象,用于判断GT应用是否已安装
if (!isGTInstalled(app)) {
// 如GT未安装,各模块采用空实现,清理connect过程的缓存
setConnState(CONNECT_STATE_NOT_INSTALLED);
return false;
}
// 初始化Handler,在Handler中绑定GT服务并拉起GT应用
splashHandler = new SplashHandler(app);
gtServiceConnection = new GTServiceConnection(splashHandler);
outParaManager = new OutParaManagerInternal();
inParaManager = new InParaManagerInternal();
loader.loadInParas(inParaManager.getUserInterface());
loader.loadOutParas(outParaManager.getUserInterface());
// 可以将出入参放入aidl任务缓存队列了
curConnState.registerInParas(inParaManager.getAndClearTempParas());
curConnState.registerOutParas(outParaManager.getAndClearTempParas());
Intent gtIntent = new Intent();
gtIntent.setAction(GTInternal.ACTION);
gtIntent.setPackage(GTInternal.GT_PACKAGE_NAME);
Message msg = Message.obtain();
msg.what = SplashHandler.MSG_START_CONNECT_GT;
msg.obj = gtIntent;
splashHandler.sendMessage(msg);
}
return true;
}
public void setHostContext(Context hostContext){
context = hostContext;
}
public Context getHostContext(){
return context;
}
/**
* 通过被测应用的Context查找GT主应用是否存在,
* 如果存在,则返回一个GT应用的Context对象,注意该Context并非GT应用中的对象,
* 只是GT应用Context的一个镜像
*
* @param hostContext 被测应用的Context
*
* @return GT应用是否已安装
*/
private boolean isGTInstalled(Context hostContext) {
return getGTContext(hostContext) == null ? false : true;
}
private static Context getGTContext(Context hostContext)
{
try {
Context context = hostContext.createPackageContext(
GTInternal.GT_PACKAGE_NAME, Context.CONTEXT_INCLUDE_CODE
| Context.CONTEXT_IGNORE_SECURITY);
return context;
} catch (NameNotFoundException e) {
Log.d(GTInternal.GT_PACKAGE_NAME, "GT is uninstall.");
}
return null;
}
public void initComImpl() {
gtCom = new ComImpl(gtService);
}
/**
* 当前是否可以尝试去连接GT
* @return
*/
public boolean isCanTryDisconnect()
{
if (curConnState == CONNECT_STATE_CONNECTED)
{
return true;
}
return false;
}
/**
* 与GT应用断连
*
* @param hostContext
* 宿主应用的Context
*/
public void disconnect(Context hostContext) {
if (isCanTryDisconnect())
{
setConnState(CONNECT_STATE_DISCONNECTING);
boolean result = disconnectGT(hostContext.getPackageName());
if(result){
if (null != splashHandler)
{
splashHandler.sendEmptyMessage(SplashHandler.MSG_START_DISCONNECT_GT);
}
}
}
}
public void applyDisconnect(Context hostContext){
Intent intent = new Intent("com.tencent.wstt.gt.disconnected");
intent.putExtra("param_clean_ParaList", false);
intent.putExtra("param_remove_client", hostContext.getPackageName());
context.sendBroadcast(intent);
if(null != splashHandler){
splashHandler.sendEmptyMessage(SplashHandler.MSG_START_DISCONNECT_GT);
}
}
public int checkIsCanConnect(String cur_pkgName){
return gtCom.checkIsCanConnect(cur_pkgName, GTConfig.INTERVAL_VID);
}
public void initConnectGT(String pkgName, int pid){
gtCom.initConnectGT(pkgName, pid);
}
public boolean disconnectGT(String cur_pkgName){
if(null != gtCom){
return gtCom.disconnectGT(cur_pkgName);
}else{
return false;
}
}
/**
* 打印日志,INFO级别
*
* @param tag
* 日志标签
* @param msg
* 日志内容
*/
public void logI(String tag, String msg) {
if (null != curConnState)
{
curConnState.logI(tag, msg);
}
}
/**
* 打印日志,DEBUG级别
*
* @param tag
* 日志标签
* @param msg
* 日志内容
*/
public void logD(String tag, String msg) {
if (null != curConnState)
{
curConnState.logD(tag, msg);
}
}
/**
* 打印日志,WARNING级别
*
* @param tag
* 日志标签
* @param msg
* 日志内容
*/
public void logW( String tag, String msg) {
if (null != curConnState)
{
curConnState.logW(tag, msg);
}
}
/**
* 打印日志,ERROR级别
*
* @param tag
* 日志标签
* @param msg
* 日志内容
*/
public void logE(String tag, String msg) {
if (null != curConnState)
{
curConnState.logE(tag, msg);
}
}
/**
* 开始一次线程内耗时统计。
* @param group 统计分组
* @param tag 统计标签
*/
public void startTimeInThread(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
curConnState.startTimeInThread(group, tag, exkeys);
}
}
/**
* 结束一次线程内耗时统计。
* @param group 统计分组
* @param tag 统计标签
*/
public long endTimeInThread(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
return curConnState.endTimeInThread(group, tag, exkeys);
}
return -1;
}
/**
* 开始一次全局耗时统计。不区分被测程序侧和控制台侧,所以可以进行跨应用统计
* @param group 统计分组
* @param tag 统计标签
*/
public void startTime(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
curConnState.startTime(group, tag, exkeys);
}
}
/**
* 结束一次全局耗时统计。
* @param group 统计分组
* @param tag 统计标签
*/
public long endTime(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
return curConnState.endTime(group, tag, exkeys);
}
return -1;
}
public void startTimeGlobal(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
curConnState.startTimeAcrossProcess(group, tag, exkeys);
}
}
public void endTimeGlobal(String group, String tag, int...exkeys)
{
if (null != curConnState)
{
curConnState.endTimeAcrossProcess(group, tag, exkeys);
}
}
/**
* 为当前线程设置未捕获异常的处理器
*/
public void setDefaultUncaughtExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new GTUncaughtExceptionHandler());
}
//=======================================关于输出参数=======================================================
public void setOutPara(String paraName, Object value, boolean isGlobal) {
if (null == paraName || null == value)
{
return;
}
if(null != curConnState){
curConnState.setOutPara(paraName, value, isGlobal);
}
}
//=======================================关于输入参数=======================================================
public void setInPara(String key, String newValue, boolean isGlobal) {
if(null != curConnState){
curConnState.setInPara(key, newValue, isGlobal);
}
}
public String getInPara(String ParaName, String origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public boolean getInPara(String ParaName, boolean origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public int getInPara(String ParaName, int origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public double getInPara(String ParaName, double origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public float getInPara(String ParaName, float origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public long getInPara(String ParaName, long origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public short getInPara(String ParaName, short origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public byte getInPara(String ParaName, byte origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
public void setProfilerEnable(boolean flag)
{
curConnState.setProfilerEnable(flag);
}
public void setFloatViewFront(boolean flag)
{
curConnState.setFloatViewFront(flag);
}
public void setCommand(String receiver, Bundle bundle)
{
curConnState.setCommand(receiver, bundle);
}
public char getInPara(String ParaName, char origVal, boolean isGlobal) {
return curConnState.getInPara(ParaName, origVal, isGlobal);
}
/*
* modify on 2015.3.5 状态切换加同步保护
*/
synchronized public void setConnState(IConnState state)
{
if (this.curConnState != null)
{
this.curConnState.finish();
}
Log.w("setConnState", "Pre State:" + this.curConnState.getClass().getName());
state.init(this.curConnState);
state.init(this.curConnState, gtService);// 只有ConnectedState方法需要
this.curConnState = state;
Log.w("setConnState", "Now State:" + this.curConnState.getClass().getName());
}
public String getGTConsoleVersion()
{
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_GET_VERSION);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
return null;
}
String version = bundle.getString(Functions.GT_CMD_KEY_VERSION);
return version;
}
return null;
}
/**
* 设置当前的GT连接监听对象
* @param listener
*/
public void setGTConnectListener(GTConnectListener listener)
{
this.gTConnectListener = listener;
}
/**
* 获取当前的GT连接监听对象
* @return
*/
public GTConnectListener getGTConnectListener()
{
return gTConnectListener;
}
/**
* 启动GT进行当前进程的数据采集,执行该命令前GT应已连接
*/
public void startProcTest(int pid, String pkgName)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_START_PROCTEST);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
/**
* 停止GT对当前进程数据的采集,执行该命令前GT应已连接
*
* @param saveFolderName
* 保存目录的名称,此目录会保存在/sdcard/GT/default/下,
* 如果目录名为null,默认的目录名是GW_DATA
*/
public void endProcTest(int pid, String saveFolderName)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_END_PROCTEST);
String pkgName = context.getPackageName();
bundle.putString("saveFolderName", saveFolderName);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
/**
* 停止GT对当前进程数据的采集,并清理测试数据,执行该命令前GT应已连接
*
* @param saveFolderName
* 保存目录的名称,此目录会保存在/sdcard/GT/default/下,
* 如果目录名为null,默认的目录名是GW_DATA,
* 每次保存后,GT会把缓存的本次测试数据清空。
*/
public void endTestAndClear(int pid, String saveFolderName)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_END_TEST_AND_CLEAR);
String pkgName = context.getPackageName();
bundle.putString("saveFolderName", saveFolderName);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
/**
* 清理测试数据,执行该命令前必须先执行过endProcTest方法,否则清理动作无效
*/
public void clearTestDatas()
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_TEST_DATA_CLEAR);
String pkgName = context.getPackageName();
bundle.putString("pkgName", pkgName);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void startSample(int pid, String target)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_START_SAMPLE);
String pkgName = context.getPackageName();
bundle.putString("target", target);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void stopSample(int pid, String target)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_STOP_SAMPLE);
String pkgName = context.getPackageName();
bundle.putString("target", target);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void sample(int pid, String target)
{
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_SAMPLE);
String pkgName = context.getPackageName();
bundle.putString("target", target);
bundle.putString("pkgName", pkgName);
bundle.putInt("pid", pid);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void setPerfDataSampleRate(int ms) {
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_SET_SAMPLE_RATE);
bundle.putInt("sampleRate", ms);
curConnState.setCommand("", bundle);
}
/**
* 直接采集某一指标
* @param target 指标标识,要与控制台对应
* @since 2.2.6.3
*/
public static void sample(String target)
{
if (!GT.isEnable())
{
return;
}
GTInternal.INSTANCE.sample(-1, target);
}
/**
* 开始耗时统计
* @since 2.2.6.3
*/
public void startTimeStatistics()
{
this.setProfilerEnable(true);
}
/**
* 暂停耗时统计
* @since 2.2.6.3
*/
public void stopTimeStatistics()
{
this.setProfilerEnable(false);
}
/**
* 结束耗时统计并保存
* @param filename 保存的文件名
*/
public void endTimeStatistics(String filename)
{
if (null == filename)
{
return;
}
// 不走状态,直接调同步命令的服务
if (null != gtService)
{
Bundle bundle = new Bundle();
bundle.putString(Functions.GT_COMMAND, "");
bundle.putInt(Functions.GT_COMMAND_KEY, Functions.GT_CMD_END_ET_AND_CLEAR);
bundle.putString("filename", filename);
try {
gtService.setCommondSync(bundle);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}