public class FlashController {
	private final static String TAG = "FlashController";
	private static FlashController mInstance;

	public final static int LEVEL_MAX = 7;
	public final static int LEVEL_OFF = 0;
	private int currentLevel;

	private Parameters parameters;
	private Camera camera;

	private int switchSound;
	private SoundPool soundPool;
	private boolean isSoundInit;// 是否可以播放
	private boolean enableSound;// 是否可以开声音

	private long AUTO_CLOSE_TIME_INTERVAL = 0;
	private AlarmManager alarmManager;// FIXME这个可以Softreference
	private PendingIntent autoCloseRequest;
	private long flashOpenTimeMills = 0;

	private List<OnFlashLevelChangedListener> observers;
	private int lisenseState = -1;
	private boolean lisenseEnable;
	private FlashHelper flashHelper;

	private Object CAMERA_LOCK = new Object();
	private boolean isCameraInited = false;

	// FIXME 执行完毕之后是否需要显式去停止
	private Runnable cameraInitTask = new Runnable() {

		@Override
		public void run() {
			initCamera(hasCameraReleased());
		}
	};

	private FlashController() {
		lisenseEnable = true;
		currentLevel = LEVEL_OFF;
		flashHelper = new FlashHelper();
		enableSound = MPreferenceManager.getInstance().isSwitchSoundOn();
	}

	public static FlashController getInstance() {
		if (mInstance == null)
			mInstance = new FlashController();
		return mInstance;
	}

	// FIXME 在哪释放
	public void releaseInstance() {
		if (mInstance != null) {
			relaseSwitchSound();
			releaseAutoCloseMgr();
			releaseCamera();
			mInstance = null;
			observers.removeAll(observers);
		}
	}

	// FIXME 线程执行完毕之后需不需要停止
	public void initCameraSync() {
		Thread cameraInitThread = new Thread(cameraInitTask);
		cameraInitThread.start();
	}

	/*
	 * 回到桌面的时候需要调用一次
	 */
	public void initCamera() {
		initCamera(hasCameraReleased());
	}
	
	private void initCamera(boolean needReconnect) {
		synchronized (CAMERA_LOCK) {
			if(isCameraInited == false) {
				if (needReconnect && camera != null) {
					camera = null;
				}
				try {
					if (camera == null)
						camera = Camera.open();
					parameters = camera.getParameters();
				} catch (RuntimeException re) {
					parameters = null;
				}
				if (needReconnect && currentLevel > LEVEL_OFF) {
					currentLevel = LEVEL_OFF;
					notifyFlashLevelChanged();//重新打开需要通知对应的观察者
					turnFlashOffIfCameraReleased();
				}
				isCameraInited = parameters != null;
			}
		}
	}
	
	/*
	 * 关灯灭屏时释放Camera，亮屏幕时不着急调用，首次调用时打开
	 */
	public void releaseCamera() {
		synchronized (CAMERA_LOCK) {
			if (camera != null) {
				try {
					camera.release();
				} catch (RuntimeException re) {
					Log.v(TAG, "camera already released");
				}
				camera = null;
				isCameraInited = false;
			}
		}
	}

	public void initSwitchSound() {
		if (enableSound && (isSoundInit == false || soundPool == null)) {
			soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
			soundPool.setOnLoadCompleteListener(soundInitListener);
			switchSound = soundPool.load(FlashApp.getContext(),
					R.raw.flashswitch, 1);
		}
	}

	OnLoadCompleteListener soundInitListener = new OnLoadCompleteListener() {
		@Override
		public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
			isSoundInit = true;
		}
	};

	/*
	 * 关灯灭屏时释放，亮屏幕时不着急调用，首次调用时打开
	 */
	public void relaseSwitchSound() {
		if (soundPool != null && isSoundInit) {
			soundPool.release();
			soundPool = null;
			isSoundInit = false;
		}
	}

	public void enableSound() {
		enableSound = true;
		initSwitchSound();// 打开这个时，用户应该很快想去试试，所以提前加载
	}

	public void disabelSound() {
		enableSound = false;
		relaseSwitchSound();
	}

	// FIXME 这样还是不能确保，可能那一次没有声音
	public void playSwitchSound() {
		initSwitchSound();
		if (enableSound && isSoundInit)
			soundPool.play(switchSound, 1.5f, 1.5f, 0, 0, 1);
	}

	private void initAutoCloseMgr() {
		if (alarmManager == null) {
			alarmManager = (AlarmManager) FlashApp.getContext()
					.getSystemService(Context.ALARM_SERVICE);
		}
	}

	public void releaseAutoCloseMgr() {
		cancelAutoCloseTask();
		alarmManager = null;
		autoCloseRequest = null;
	}

	/*
	 * 调用时机 1. 开灯的时候 2. 调整设置项的时候 FIXME 如果时间已经过了
	 */
	private void requestAutoCloseTask() {
		requestAutoCloseTask(0);
	}
	
	public void requestAutoCloseTask(long autoCloseTimInterval) {
		initAutoCloseMgr();
		
		if(autoCloseTimInterval > 0) {
			AUTO_CLOSE_TIME_INTERVAL = autoCloseTimInterval;
		} else if(AUTO_CLOSE_TIME_INTERVAL == 0) {
			AUTO_CLOSE_TIME_INTERVAL = MPreferenceManager.getInstance().getAutoCloseTime() * 60000;
		}
		
		if (currentLevel > LEVEL_OFF) {
			long triggleAtMills = flashOpenTimeMills + AUTO_CLOSE_TIME_INTERVAL;
			Intent requestIntent = ServiceHelper.getAutoCloseIntent();
			autoCloseRequest = PendingIntent.getService(FlashApp.getContext(),
					0, requestIntent, PendingIntent.FLAG_CANCEL_CURRENT);
			alarmManager
					.set(AlarmManager.RTC, triggleAtMills, autoCloseRequest);
		}
	}

	public void cancelAutoCloseTask() {
		if (autoCloseRequest != null) {
			alarmManager.cancel(autoCloseRequest);
			autoCloseRequest = null;
		}
	}

	public int toggleFlash() {
		initCamera();
		if (currentLevel == LEVEL_OFF) {
			turnFlashOn();
		} else {
			turnFlashOff();
		}
		return currentLevel;
	}

	private void turnFlashOn() {
		if (isCameraInited && currentLevel == LEVEL_OFF) {
			parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
			try {
				camera.setParameters(parameters);
			} catch (RuntimeException re) {
				initCamera(true);
				parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
			}
			currentLevel = LEVEL_MAX;
			flashOpenTimeMills = System.currentTimeMillis();

			requestAutoCloseTask();
			playSwitchSound();
		}
	}

	public void turnFlashOff() {
		if (isCameraInited && currentLevel > LEVEL_OFF) {
			parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
			try {
				camera.setParameters(parameters);
			} catch (RuntimeException re) {
				initCamera(true);
				parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
			}
			currentLevel = LEVEL_OFF;
			flashOpenTimeMills = 0;
			cancelAutoCloseTask();

			playSwitchSound();
		}
	}
	
	public void turnFlashOffIfCameraReleased() {
		if(currentLevel > LEVEL_OFF) {
			currentLevel = LEVEL_OFF;
			flashOpenTimeMills = 0;
	
			cancelAutoCloseTask();
		}
	}
	/*
	 * 调节亮度需要lisenseEnable才可以
	 */
	public int turnFlashUp() {
		if (lisenseEnable && currentLevel < LEVEL_MAX) {
			flashHelper.changeFlashLight(true);
			currentLevel++;
		}
		return currentLevel;
	}

	public int turnFlashDown() {
		if (lisenseEnable && currentLevel > LEVEL_OFF + 1) {
			flashHelper.changeFlashLight(false);
			currentLevel--;
		}
		return currentLevel;
	}

	public boolean hasCameraReleased() {
		boolean hasReleased = false;
		if(camera == null) {
			hasReleased = true;
			isCameraInited = false;
		} else {
			try {
				parameters = camera.getParameters();
			} catch (RuntimeException re) {
				hasReleased = true;
				isCameraInited = false;
			}
		}
		return hasReleased;
	}

	public int getCurrentLevel() {
		return currentLevel;
	}

	public boolean isFlashOn() {
		return currentLevel > LEVEL_OFF;
	}

	public void notifyFlashLevelChanged() {
		if (observers != null) {
			for (OnFlashLevelChangedListener observer : observers) {
				observer.onFlashLevelChanged(currentLevel);
			}
		}
	}

	public void setLisenseState(int lisenseState) {
		if (this.lisenseState != lisenseState) {
			this.lisenseState = lisenseState;

			lisenseEnable = lisenseState == MLisenseMangaer.STATE_PURCHASED
					|| lisenseState == MLisenseMangaer.STATE_TRYING;
			
			if(!lisenseEnable) {
				//关闭对应设置项，并通知更新
				MPreferenceManager prefsMgr = MPreferenceManager.getInstance();
				prefsMgr.toggleKeyguardPanel(false, true);
				prefsMgr.toggleLauncherPanel(false, true);
				//FIXME preference的写入考虑使用队列的形式
			}
		}
	}
	
	public int getLisenseState() {
		return lisenseState;
	}
	
	public boolean islisenseEnable() {
		return lisenseEnable;
	}
	
	public boolean isPurchased() {
		return lisenseState == MLisenseMangaer.STATE_PURCHASED;
	}
	
	public void addObserver(OnFlashLevelChangedListener listener) {
		if (observers == null)
			observers = new ArrayList<OnFlashLevelChangedListener>();
		if (!observers.contains(listener)) {
			observers.add(listener);
		}
	}

	public void removeObserver(OnFlashLevelChangedListener listener) {
		if (observers != null && observers.contains(listener)) {
			observers.remove(listener);
		}
	}

	public interface OnFlashLevelChangedListener {
		public void onFlashLevelChanged(int currentLevel);
	}
} public interface OnFlashLevelChangedListener {
	public void onFlashLevelChanged(int currentLevel);
} public class ServiceHelper {
	public static void startLauncherPanelService() {
		Intent intent = new Intent(PanelService.ACTION_LAUNCHER);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_START);
		FlashApp.getContext().startService(intent);
	}

	public static void stopLauncherPanelService() {
		Intent intent = new Intent(PanelService.ACTION_LAUNCHER);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_STOP);
		FlashApp.getContext().startService(intent);
	}

	public static void startKeyguardPanelService() {
		Intent intent = new Intent(PanelService.ACTION_KEYGUARD);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_START);
		FlashApp.getContext().startService(intent);
	}

	public static void stopKeyguardPanelService() {
		Intent intent = new Intent(PanelService.ACTION_KEYGUARD);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_STOP);
		FlashApp.getContext().startService(intent);
	}

	public static void callPanelServiceWhenScreenOn() {
		Intent intent = new Intent(PanelService.ACTION_PANEL_SERVICE);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_SCREEN_ON);
		FlashApp.getContext().startService(intent);
	}

	public static void callPanelServiceWhenScreenOff() {
		Intent intent = new Intent(PanelService.ACTION_PANEL_SERVICE);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_SCREEN_OFF);
		FlashApp.getContext().startService(intent);
	}

	public static void callPanelServiceWhenUserPresent() {
		Intent intent = new Intent(PanelService.ACTION_PANEL_SERVICE);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_USER_PRESENT);
		FlashApp.getContext().startService(intent);
	}

	/*
	 * service启动入口
	 * 1. MainActivity界面，用户点击桌面icon进入
	 * 2. 重启，boot_complete广播
	 *
	 * 
	 */
	public static void startPanelService() {
		MPreferenceManager mPrefsMgr = MPreferenceManager.getInstance();
		boolean isLauncherPanelService = mPrefsMgr.isLauncherPanelShown();
		boolean isKeyguardPanelService = mPrefsMgr.isKeyguardPanelShown();
		if (isLauncherPanelService && isKeyguardPanelService) {
			Intent intent = new Intent(PanelService.ACTION_PANEL_SERVICE);
			intent.putExtra(PanelService.CONTROL_TYPE_KEY,
					PanelService.CONTROL_TYPE_START);
			FlashApp.getContext().startService(intent);
		} else if (isLauncherPanelService) {
			startLauncherPanelService();
		} else if (isKeyguardPanelService) {
			startKeyguardPanelService();
		}
	}
	
	public static void stopPanelService() {
		Intent intent = new Intent(PanelService.ACTION_PANEL_SERVICE);
		intent.putExtra(PanelService.CONTROL_TYPE_KEY,
				PanelService.CONTROL_TYPE_STOP);
		FlashApp.getContext().startService(intent);
	}
	
	public static Intent getAutoCloseIntent() {
		Intent requestIntent = new Intent(
				ControlService.ACTION_AUTO_CLOSE);
		requestIntent.putExtra(ControlService.CONTROL_TYPE_KEY, ControlService.CONTROL_TYPE_SHOW_ACDIALOG);
		return requestIntent;
	}
} public class LightmeConstants {
	public final static String APP_IDENTIFY = "6c1e42416976493cbdbe254554b4bef2";
} public class MConnectHelper {
	public static final String MSTORE_URI_HEADER = "mstore:";
    public static final String SOFTWARE_URL_BASE = "http://app.meizu.com/phone/apps/";
    public static final String MSTORE_IDENTIFY = "45e228a5a533488c8d46f7b5284d4ec7";
    
	private Context context;
	private Resources resource;

	public MConnectHelper(Context context) {
		resource = context.getResources();
		this.context = context;
	}
	
	public void sendLockMsgWithMail(int lisenseState) {
		String subject = resource.getString(R.string.lock_subject);
		String defaultContent = String.format(resource
				.getString(R.string.lock_content_default), MLisenseMangaer.getLisenseInfo(lisenseState));
		sendInfoWithMail(subject, defaultContent);
	}
	
	public void sendFeedbackWithMail() {
		String subject = resource.getString(R.string.feedback_subject);
		String defaultContent = resource
				.getString(R.string.feedback_content_default);
		sendInfoWithMail(subject, defaultContent);
	}

	private void sendInfoWithMail(String subject, String defaultContent) {
		Intent intent = getBaseShareIntent();

		List<ResolveInfo> resInfos = context.getPackageManager()
				.queryIntentActivities(intent, 0);
		List<Intent> targetIntents = null;
		Intent targetIntent = null;
		if (resInfos != null && !resInfos.isEmpty()) {
			targetIntents = new ArrayList<Intent>();
			for (ResolveInfo resInfo : resInfos) {
				ActivityInfo activityInfo = resInfo.activityInfo;
				if (activityInfo.packageName.contains("mail")) {
					targetIntent = getMailIntent(subject, defaultContent);
					targetIntent.setPackage(activityInfo.packageName);
					targetIntents.add(targetIntent);
				}
			}
			
			if(targetIntents.size() == 0)//FIXME 对于卸载邮箱的用户
				return ;
			
			Intent chooserIntent = Intent.createChooser(
					targetIntents.remove(0), "选择邮件应用");
			
			if (chooserIntent == null)
				return;
			chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
					targetIntents.toArray(new Intent[] {}));

			try {
				context.startActivity(chooserIntent);
			} catch (android.content.ActivityNotFoundException ex) {
				Toast.makeText(context, "Can't find share component to share",
						Toast.LENGTH_SHORT).show();
			}
		}
	}

	public Intent getMailIntent(String subject, String defaultContent) {
		Intent emailIntent = getBaseShareIntent();
		String[] emailReciver = new String[] { "dichengsiyu@gmail.com" };

		emailIntent.putExtra(Intent.EXTRA_EMAIL, emailReciver);
		emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
		emailIntent.putExtra(Intent.EXTRA_TEXT, defaultContent);
		return emailIntent;
	}

	private Intent getBaseShareIntent() {
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("text/plain");
		return intent;
	}

	public void jumpToMarket(String appIdentify) {
		try {
			Intent intent = new Intent();
			intent.setData(Uri.parse(MSTORE_URI_HEADER
					+ SOFTWARE_URL_BASE + appIdentify));
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			intent.setClassName("com.meizu.mstore",
					"com.meizu.mstore.MStoreMainPlusActivity");
			context.startActivity(intent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
} public class MDisplayHelper {
	
	private DisplayMetrics displayMetrics;
	private int screenWidth = 0;
	private float density = 0;

	public MDisplayHelper() {
		Context context = FlashApp.getContext();
		displayMetrics = context.getResources().getDisplayMetrics();
	}
	
	public DisplayMetrics getDisplayMetrics() {
		return displayMetrics;
	}
	
	public int getScreenWidth() {
		return displayMetrics.widthPixels;
	}
	
	public int getScreenHeight() {
		return displayMetrics.widthPixels;
	}
	
	public float getDensity() {
		if(density == 0)
			density = displayMetrics.density;
		return density;
	}
	
	public int dpiToPx(float dip) {
		return (int)(dip * getDensity() + 0.5f);
	}
	
	public int pxToDpi(float px) {
		return (int)(px / getDensity() + 0.5f);
	}
} public class MLisenseMangaer {
	private final static String TAG = "MLisenseMangaer";

	public final static int STATE_UNKNOWN = 0;
	public final static int STATE_PURCHASED = 1;
	public final static int STATE_TRYING = 2;
	public final static int STATE_EXPIRED = 3;

	public final static int EXPIRE_DAYS = 3;
	public final static String APK_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCB4xYVRA7w13J6dBWA+oERVDRnefb8J5N7zeD3e6JfExk76F59YRDbmDVPL+ztwwboy+R3RSQKIHM/DYymqAHnbq4m/tKXCS6BcL9MeH6Cc2xas2dNNfzOjDrb/5oqvzHI+0TPX3gU2ZML3Udsw4Q+QT+jYOgLbMYfbps3OZne5QIDAQAB/wJQnyPGfR72CNv5zR+qA4qjxSMBUSQh55awBgR4Jrwd3G+6/yH540pB/oP+GsTp0Sof/dEFaR85968aEhBGRcnpEl9OITISZRwMp654/LD6kzdsjMBjfPXiYRSLjygcbG//gOVxZbnmU2Nz5pnuFvav8wIDAQAB";

	private Context mContext;
	// 服务的实例对象
	private ILicensingService mLicensingService = null;
	private OnLisenseStateChangeListener mListener;

	public MLisenseMangaer() {
		// for local check
		this(null);
	}

	public MLisenseMangaer(OnLisenseStateChangeListener listener) {
		mListener = listener;
		mContext = FlashApp.getContext();
	}

	// 服务绑定的回调，可用于判断服务是否绑定成功
	private ServiceConnection mLicenseConnection = new ServiceConnection() {

		public void onServiceDisconnected(ComponentName name) {
			if (mListener != null)
				mListener.onRemoteServiceDisconnected();
			mLicensingService = null;
		}

		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.v(TAG, "服务绑定成功，获取服务实例");
			mLicensingService = ILicensingService.Stub.asInterface(service);
			if (mListener != null)
				mListener.onRemoteServiceConnected();
		}
	};

	public void bindRemoteService() {
		if (mLicensingService == null) {
			// 绑定服务
			Intent serviceIntent = new Intent();
			serviceIntent.setAction(ILicensingService.class.getName());
			mContext.bindService(serviceIntent, mLicenseConnection,
					Context.BIND_AUTO_CREATE);
		} else {
			if (mListener != null)
				mListener.onRemoteServiceConnected();
		}
	}

	public void unbindRemoteService() {
		// 如果服务已经绑定，在退出时需要反绑服务
		if (mLicensingService != null) {
			mContext.unbindService(mLicenseConnection);
		}
	}

	// doCheck()方法演示了如何使用license服务来验证授权是否合法
	public int doRemoteCheck() {

		// 该第三方应用的包名,可使用getApplication().getPackageName()获取本应用包名
		final String packageName = mContext.getPackageName();

		// 保存服务验证的结果值
		LicenseResult result = null;
		int lisenseState = STATE_UNKNOWN;
		if (mLicensingService != null) {
			try {
				// 调用服务接口进行验证,获取返回的结果值
				// FIXME 为什么有的时候为空
				result = mLicensingService.checkLicense(packageName);
			} catch (RemoteException e) {
				Log.e(TAG, "获取证书失败");
				// 作为UNKNOWN来处理，这种异常不需要显示错误
				lisenseState = STATE_TRYING;
			}

			if (result != null
					&& result.getResponseCode() == LicenseResult.RESPONSE_CODE_SUCCESS) {
				// license验证服务验证通过,需要接着对服务返回的结果再次进行校验(使用自己的公钥进行验证)
				boolean bSuccess = LicenseCheckHelper.checkResult(
						APK_PUBLIC_KEY, result);

				if (bSuccess
						&& result.getPurchaseType() == LicenseResult.PURCHASE_TYPE_NORMAL) {
					// 验证成功，并且为正式版本
					lisenseState = STATE_PURCHASED;

					// FIXME 获取子产品
				} else if (result.getPurchaseType() == LicenseResult.PURCHASE_TYPE_TRIAL) {
					// 验证成功，是试用版本
					// 该方法返回license文件的生成日期（注:该日期的值只精确到天，即时分秒为随机值）
					Calendar beginCal = result.getStartDate();
					// Log.v("", "试用开始的日期为: " + beginCal.get(Calendar.YEAR) +
					// "年"
					// + (beginCal.get(Calendar.MONTH) + 1) + "月"
					// + beginCal.get(Calendar.DAY_OF_MONTH) + "日");
					/**
					 * 以下是可供参考的过期判断
					 */
					// 你自己定义的过期天数
					final int expireDays = 3;
					// 获取当前日期
					Calendar nowCal = Calendar.getInstance();
					// 求剩余的天数
					long dif = nowCal.getTimeInMillis()
							- beginCal.getTimeInMillis();
					int passDay = (int) (dif / (24 * 60 * 60 * 1000));
					int left = expireDays - passDay;
					if (left > 0) {
						// 未过期
						Log.v(TAG, "未过期");
						lisenseState = STATE_TRYING;
					} else {
						// 过期
						Log.e(TAG, "过期");
						lisenseState = STATE_EXPIRED;
					}
					// FIXME 获取子产品
				} else {
					// 验证不成功或者版本类型不对，可按试用版处理
					// FIXME 状态一定要对，作为UNKNOWN来处理
					lisenseState = STATE_TRYING;
					Log.e(TAG, "license验证不通过");
				}
			} else {
				// license验证服务验证不通过
				lisenseState = STATE_UNKNOWN;// 用友盟来统计？
				if (result!= null && result.getResponseCode() == LicenseResult.RESPONSE_CODE_NO_LICENSE_FILE) {
					// 不存在与应用对应的license文件
					Log.e(TAG, "无对应的license文件");
				} else {
					// license文件无效
					Log.e(TAG, "license文件无效");
				}
			}
		}
		MPreferenceManager.getInstance().setLocalLisenseState(lisenseState);
		return lisenseState;
	}

	public static String getLisenseInfo(int lisenseState) {
		Resources resource = FlashApp.getContext().getResources();
		String lisenseInfo;
		switch (lisenseState) {
		case STATE_TRYING:
			lisenseInfo = resource.getString(R.string.lisense_state_trying);
			break;
		case STATE_EXPIRED:
			lisenseInfo = resource.getString(R.string.lisense_state_expired);
			break;
		case STATE_UNKNOWN:
			lisenseInfo = resource.getString(R.string.lisense_state_unknown);
			break;
		default:
			lisenseInfo = null;
			break;
		}
		return lisenseInfo;
	}

	public interface OnLisenseStateChangeListener {
		public void onRemoteServiceConnected();
		public void onRemoteServiceDisconnected();
	}
} public class MPreferenceManager {
	private static MPreferenceManager mInstance;
	private SharedPreferences mPrefs;
	
	public final static String KEY_AUTO_CLOSE = "auto_close";
	public final static String KEY_AUTO_CLOSE_TIME = "auto_close_time";
	
	public final static String KEY_SHOW_LAUNCHER_PANEL = "show_launcher_panel";
	public final static String KEY_PANEL_X = "panel_x";
	public final static String KEY_PANEL_Y = "panel_y";
	public final static String KEY_SHOW_KEYGUARD_PANEL = "show_keyguard_panel";
	public final static String KEY_KEYGURAD_SHOCK_ENABLE = "enable_keyguard_shock";
	public final static String KEY_VERSION_CODE = "version_code";
	public final static String KEY_FIRST_START_DATE = "first_start_date";
	public final static String KEY_FIRST_SHOW_LAUNCHER = "first_show_launcher";
	public final static String KEY_FIRST_SHOW_KEYGUARD = "first_show_keyguard";
	public final static String KEY_ENABLE_SWITCH_SOUND = "enable_switch_sound";
	public final static String KEY_NEED_REFRESH_SETTING = "key_need_refresh_setting";
	
	public final static String KEY_LOCAL_LISENSE_STATE = "local_lisense_state";
	public final static String KEY_LISENSE_EXPIRED_TIMEMILLS = "lisense_expired_timemills";
	
	private MPreferenceManager() {
		mPrefs =PreferenceManager.getDefaultSharedPreferences(FlashApp.getContext());
	}
	
	public static MPreferenceManager getInstance() {
		if(mInstance == null)
			mInstance = new MPreferenceManager();
		return mInstance;
	}
	
	public void toggleLauncherPanel(boolean setShown, boolean needRefreshSetting) {
		Editor edit = mPrefs.edit();
		edit.putBoolean(KEY_SHOW_LAUNCHER_PANEL, setShown);
		if(needRefreshSetting)
			edit.putBoolean(KEY_NEED_REFRESH_SETTING, needRefreshSetting);
		edit.commit();
	}
	
	public boolean isLauncherPanelShown() {
		return mPrefs.getBoolean(KEY_SHOW_LAUNCHER_PANEL, false);
	}
	
	public void setFirstShowLauncherDate() {
		Editor edit = mPrefs.edit();
		edit.putLong(KEY_FIRST_SHOW_LAUNCHER, System.currentTimeMillis());
		edit.commit();
	}
	
	public long getFirstShowLauncherDate() {
		return mPrefs.getLong(KEY_FIRST_SHOW_LAUNCHER, 0);
	}
	
	public void toggleKeyguardPanel(boolean setShown, boolean needRefreshSetting) {
		Editor edit = mPrefs.edit();
		edit.putBoolean(KEY_SHOW_KEYGUARD_PANEL, setShown);
		if(setShown == false)
			edit.putBoolean(KEY_KEYGURAD_SHOCK_ENABLE, false);
		if(needRefreshSetting)
			edit.putBoolean(KEY_NEED_REFRESH_SETTING, needRefreshSetting);
		edit.commit();
	} 
	
	public boolean isKeyguardPanelShown() {
		return mPrefs.getBoolean(KEY_SHOW_KEYGUARD_PANEL, false);
	}
	
	public void toggleKeyguardShock(boolean enable) {
		Editor edit = mPrefs.edit();
		edit.putBoolean(KEY_KEYGURAD_SHOCK_ENABLE, enable);
		edit.commit();
	}
	
	public boolean isKeyguardShockEnable() {
		return mPrefs.getBoolean(KEY_KEYGURAD_SHOCK_ENABLE, false);
	}
	
	public void setFirstShowKeyguardDate() {
		Editor edit = mPrefs.edit();
		edit.putLong(KEY_FIRST_SHOW_KEYGUARD, System.currentTimeMillis());
		edit.commit();
	}
	
	public long getFirstShowKeyguardDate() {
		return mPrefs.getLong(KEY_FIRST_SHOW_KEYGUARD, 0);
	}
	
	public void setPanelPos(int x, int y) {
		Editor edit = mPrefs.edit();
		edit.putInt(KEY_PANEL_X, x);
		edit.putInt(KEY_PANEL_Y, y);
		edit.commit();
	}
	
	public Point getPanelPos() {
		int x = mPrefs.getInt(KEY_PANEL_X, -1);
		int y = mPrefs.getInt(KEY_PANEL_Y, -1);
		if(x == -1 || y == -1)
			return null;
		else
			return new Point(x, y);
	}
	
	public void clearPanelPos() {
		Editor edit = mPrefs.edit();
		edit.remove(KEY_PANEL_X);
		edit.remove(KEY_PANEL_Y);
		edit.commit();
	}
	
	public long getFirtStartDate() {
		return mPrefs.getLong(KEY_FIRST_START_DATE, 0);
	}
	
	public void setVersionCode(int versionCode) {
		Editor edit = mPrefs.edit();
		edit.putInt(KEY_VERSION_CODE, versionCode);
		edit.commit();
	}
	
	public int getVersionCode() {
		return mPrefs.getInt(KEY_VERSION_CODE, 0);
	}
	
	public void setFirstStartDate() {
		Editor edit = mPrefs.edit();
		edit.putLong(KEY_FIRST_START_DATE, System.currentTimeMillis());
		edit.commit();
	}
	
	public boolean isAutoClose() {
		return mPrefs.getBoolean(KEY_AUTO_CLOSE, false);
	}
	
	public int getAutoCloseTime() {
		return mPrefs.getInt(KEY_AUTO_CLOSE_TIME, 2);
	}
	
	public void setAutoCloseTime(int autoCloseTime) {
		Editor edit = mPrefs.edit();
		edit.putInt(KEY_AUTO_CLOSE_TIME, autoCloseTime);
		edit.commit();
	}
	
	public boolean isSwitchSoundOn() {
		return mPrefs.getBoolean(KEY_ENABLE_SWITCH_SOUND, true);
	}
	
	public int getLocalLisenseState() {
		return mPrefs.getInt(KEY_LOCAL_LISENSE_STATE, MLisenseMangaer.STATE_UNKNOWN);
	}
	
	public void setLocalLisenseState(int lisenseState) {
		Editor edit = mPrefs.edit();
		edit.putInt(KEY_LOCAL_LISENSE_STATE, lisenseState);
		edit.commit();
	}
	
	public long getExpiredTimeMills() {
		return mPrefs.getLong(KEY_LISENSE_EXPIRED_TIMEMILLS, 0);
	}
	
	public void setExpiredTimeMills(long expiredTimeMills) {
		Editor edit = mPrefs.edit();
		edit.putLong(KEY_LISENSE_EXPIRED_TIMEMILLS, expiredTimeMills);
		edit.commit();
	}
	
	public boolean needRefreshSetting() {
		return mPrefs.getBoolean(KEY_NEED_REFRESH_SETTING, false);
	}
	
	public void setNeedRefreshSetting(boolean needRefresh) {
		Editor edit = mPrefs.edit();
		edit.putBoolean(KEY_NEED_REFRESH_SETTING, needRefresh);
		edit.commit();
	}
} public class SmartBarUtils {

    /**
     * 调用 ActionBar.setTabsShowAtBottom(boolean) 方法。
     * 
     * <p>如果 android:uiOptions="splitActionBarWhenNarrow"，则可设置ActionBar Tabs显示在底栏。
     * 
     * <p>示例：</p>
     * <pre class="prettyprint">
     * public class MyActivity extends Activity implements ActionBar.TabListener {
     * 
     *     protected void onCreate(Bundle savedInstanceState) {
     *         super.onCreate(savedInstanceState);
     *         ...
     *         
     *         final ActionBar bar = getActionBar();
     *         bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
     *         SmartBarUtils.setActionBarTabsShowAtBottom(bar, true);
     *         
     *         bar.addTab(bar.newTab().setText("tab1").setTabListener(this));
     *         ...
     *     }
     * }
     * </pre>
     */
    public static void setActionBarTabsShowAtBottom(ActionBar actionbar, boolean showAtBottom) {
        try {
            Method method = Class.forName("android.app.ActionBar").getMethod(
                    "setTabsShowAtBottom", new Class[] { boolean.class });
            try {
                method.invoke(actionbar, showAtBottom);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 调用 ActionBar.setActionBarViewCollapsable(boolean) 方法。
     * 
     * <p>设置ActionBar顶栏无显示内容时是否隐藏。
     * 
     * <p>示例：</p>
     * <pre class="prettyprint">
     * public class MyActivity extends Activity {
     * 
     *     protected void onCreate(Bundle savedInstanceState) {
     *         super.onCreate(savedInstanceState);
     *         ...
     *         
     *         final ActionBar bar = getActionBar();
     *         
     *         // 调用setActionBarViewCollapsable，并设置ActionBar没有显示内容，则ActionBar顶栏不显示
     *         SmartBarUtils.setActionBarViewCollapsable(bar, true);
     *         bar.setDisplayOptions(0);
     *     }
     * }
     * </pre>
     */
    public static void setActionBarViewCollapsable(ActionBar actionbar, boolean collapsable) {
        try {
            Method method = Class.forName("android.app.ActionBar").getMethod(
                    "setActionBarViewCollapsable", new Class[] { boolean.class });
            try {
                method.invoke(actionbar, collapsable);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 调用 ActionBar.setActionModeHeaderHidden(boolean) 方法。
     * 
     * <p>设置ActionMode顶栏是否隐藏。
     * 
     * <p>示例：</p>
     * <pre class="prettyprint">
     * public class MyActivity extends Activity {
     * 
     *     protected void onCreate(Bundle savedInstanceState) {
     *         super.onCreate(savedInstanceState);
     *         ...
     *         
     *         final ActionBar bar = getActionBar();
     *         
     *         // ActionBar转为ActionMode时，不显示ActionMode顶栏
     *         SmartBarUtils.setActionModeHeaderHidden(bar, true);
     *     }
     * }
     * </pre>
     */
    public static void setActionModeHeaderHidden(ActionBar actionbar, boolean hidden) {
        try {
            Method method = Class.forName("android.app.ActionBar").getMethod(
                    "setActionModeHeaderHidden", new Class[] { boolean.class });
            try {
                method.invoke(actionbar, hidden);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    
    
    /**
     * 调用ActionBar.setBackButtonDrawable(Drawable)方法
     * 
     * <p>设置返回键图标
     * 
     * <p>示例：</p>
     * <pre class="prettyprint">
     * public class MyActivity extends Activity {
     * 
     *     protected void onCreate(Bundle savedInstanceState) {
     *         super.onCreate(savedInstanceState);
     *         ...
     *         
     *         final ActionBar bar = getActionBar();
     *         // 自定义ActionBar的返回键图标
     *         SmartBarUtils.setBackIcon(bar, getResources().getDrawable(R.drawable.ic_back));
     *         ...
     *     }
     * }
     * </pre>
     */
    public static void setBackIcon(ActionBar actionbar, Drawable backIcon) {
        try {
            Method method = Class.forName("android.app.ActionBar").getMethod(
                    "setBackButtonDrawable", new Class[] { Drawable.class });
            try {
                method.invoke(actionbar, backIcon); 
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    public static void setHomeupIcon(View decorView, Drawable homeUpDrawable) {
    	
    }
    
    public static void toogleActionBar(View view, boolean show) {
        int flags = !show ? View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        			:View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        view.setSystemUiVisibility(flags);
	}
    
} public interface OnLisenseStateChangeListener {
	public void onRemoteServiceConnected();
	public void onRemoteServiceDisconnected();
} public class FlashView extends View {
	private final static String TAG = "FlashView";
	private final static int LEVEL_COUNT = 7;

	private float LEVEL_DISTANCE_INTERVAL = 20;
	private int SCREEN_WIDTH;

	//flash
	private int FLASH_BITMAP_START_X;
	
	// Flash Light
	private int FLASH_END_X_MAX;
	private int FLASH_END_X_INTERVAL;
	private int FLASH_END_X_MIN;
	private final static int FLASH_END_Y = 0;

	private int FLASH_START_SIZE;
	private int FLASH_START_Y;
	private int FLASH_START_X;

	//emotion
	private int EMOTION_POS_Y;
	private int[] emotionReses = {
			R.drawable.emotion_0,
			R.drawable.emotion_1,
			R.drawable.emotion_2,
			R.drawable.emotion_3,
			R.drawable.emotion_4,
			R.drawable.emotion_5,
			R.drawable.emotion_6,
			R.drawable.emotion_7};
	private Bitmap[] emotionBitmaps;
	
	private int[] emotionLockedReses = {
			R.drawable.emotion_locked_off,
			R.drawable.emotion_locked_on};
	private Bitmap[] emotionLockedBitmaps;
	
	//flash
	private Bitmap flashOffBitmap, flashOnBitmap;

	private final static float FLASH_ON_COLOR_H;
	private final static float FLASH_ON_COLOR_S;
	static {
		float[] hsv = new float[3];
		Color.colorToHSV(0xffd200, hsv);
		FLASH_ON_COLOR_H = hsv[0];
		FLASH_ON_COLOR_S = hsv[1];
	};
	private final static float FLASH_ON_COLOR_V_MAX = 1;
	private final static float FLASH_ON_COLOR_V_INTERVAL = 0.08f;// light
	private final static int FLASH_OFF_COLOR = 0x161616;

	private float[] mCurrentColorHSV;

	private Paint mFlashPaint;
	private Path mFlashPath;

	private int mCurrentLevel;
	private boolean lisenseEnable = true;

	private OnFlashStateChangeListener mListener;
	private GestureDetector mGestureDetector;
	private MDisplayHelper displayHelper;

	public FlashView(Context context, AttributeSet attrs) {
		super(context, attrs);

		displayHelper = new MDisplayHelper();
		DisplayMetrics metrics = displayHelper.getDisplayMetrics();
		SCREEN_WIDTH = metrics.widthPixels;

		// Flash Light
		FLASH_END_X_MAX = SCREEN_WIDTH;
		FLASH_END_X_INTERVAL = displayHelper.dpiToPx(40);
		FLASH_END_X_MIN = FLASH_END_X_MAX - FLASH_END_X_INTERVAL
				* (LEVEL_COUNT - 1);

		FLASH_START_SIZE = displayHelper.dpiToPx(28);
		FLASH_START_Y = displayHelper.dpiToPx(345);

		Resources resource = getResources();
		// Eye
		EMOTION_POS_Y = displayHelper.dpiToPx(90);
		emotionBitmaps = new Bitmap[LEVEL_COUNT + 1];
		for(int i = 0; i < LEVEL_COUNT + 1; ++i) {
			emotionBitmaps[i] = BitmapFactory.decodeResource(resource,
					emotionReses[i]);
		}
		
		emotionLockedBitmaps = new Bitmap[2];
		for(int i = 0; i < 2; ++i) {
			emotionLockedBitmaps[i] = BitmapFactory.decodeResource(resource,
					emotionLockedReses[i]);
		}
		// Flash bitmap
		flashOffBitmap = BitmapFactory.decodeResource(resource,
				R.drawable.flash_off);
		flashOnBitmap = BitmapFactory.decodeResource(resource,
				R.drawable.flash_on);
		
		mFlashPaint = new Paint();
		mFlashPaint.setAntiAlias(true);
		mFlashPaint.setColor(Color.YELLOW);
		mFlashPaint.setStyle(Paint.Style.FILL);

		mFlashPath = new Path();
		mCurrentColorHSV = new float[3];
		Color.colorToHSV(FLASH_OFF_COLOR, mCurrentColorHSV);

		mCurrentLevel = FlashController.LEVEL_OFF;
		mGestureDetector = new GestureDetector(context,
				mFlashViewGestureListener);
	}
	
	public void setLisenseState(boolean isLisenseEnable, int currentLevel) {
		this.lisenseEnable = isLisenseEnable;
		
		if (currentLevel > FlashController.LEVEL_OFF) {
			turnFlashLevel(currentLevel);
		} else {
			turnFlashOff();
		}
		mCurrentLevel = currentLevel;
	}

	public void setFlashLevel(int currentLevel) {
		if (mCurrentLevel != currentLevel) {
			if (currentLevel > FlashController.LEVEL_OFF) {
				turnFlashLevel(currentLevel);
			} else {
				turnFlashOff();
			}
			mCurrentLevel = currentLevel;
		}
	}

	private void turnFlashOff() {
		Color.colorToHSV(FLASH_OFF_COLOR, mCurrentColorHSV);
		postInvalidate();
	}

	private void turnFlashLevel(int level) {
		mCurrentColorHSV[0] = FLASH_ON_COLOR_H;
		mCurrentColorHSV[1] = FLASH_ON_COLOR_S;
		mCurrentColorHSV[2] = FLASH_ON_COLOR_V_MAX - (FlashController.LEVEL_MAX - level) * FLASH_ON_COLOR_V_INTERVAL;
		postInvalidate();
	}

	public void setOnSwitchStateChangeListener(
			OnFlashStateChangeListener listener) {
		mListener = listener;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mGestureDetector != null)
			return mGestureDetector.onTouchEvent(event);
		return super.onTouchEvent(event);
	}

	private OnGestureListener mFlashViewGestureListener = new OnGestureListener() {

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			boolean isHandleEvent = false;
			if (mListener != null) {
				mListener.onSwitchClick();
				isHandleEvent = true;
			}
			return isHandleEvent;
		}

		@Override
		public void onShowPress(MotionEvent e) {

		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			boolean isHandleEvent = false;
			if (mCurrentLevel > FlashController.LEVEL_OFF && mListener != null) {
				if (distanceY >= LEVEL_DISTANCE_INTERVAL) {
					mListener.onSwitchTurnUp();
				} else if (distanceY <= -LEVEL_DISTANCE_INTERVAL) {
					mListener.onSwitchTurnDown();
				}
				isHandleEvent = true;
			}
			return isHandleEvent;
		}

		@Override
		public void onLongPress(MotionEvent e) {
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			return false;
		}

		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}
	};

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		float centerX = SCREEN_WIDTH / 2;

		boolean isFlashOn = mCurrentLevel > FlashController.LEVEL_OFF;
		int level = isFlashOn ? mCurrentLevel : mCurrentLevel + 1;// 特殊绘制FlashOff
		float flashEndSize = FLASH_END_X_MIN + FLASH_END_X_INTERVAL
				* (level - 1);
		float flashStartXLeft = centerX - FLASH_START_SIZE / 2;
		float flashStartXRight = centerX + FLASH_START_SIZE / 2;
		float flashEndXLeft = (FLASH_END_X_MAX - flashEndSize) / 2;
		float flashEndXRight = FLASH_END_X_MAX - flashEndXLeft;

		// draw Flash
		if (!isFlashOn)
			canvas.drawBitmap(flashOffBitmap, flashStartXLeft, FLASH_START_Y, mFlashPaint);
		else
			canvas.drawBitmap(flashOnBitmap, flashStartXLeft, FLASH_START_Y, mFlashPaint);

		// draw Flash light
		mFlashPaint.setStyle(Paint.Style.FILL);
		mFlashPaint.setColor(Color.HSVToColor(mCurrentColorHSV));
		
		mFlashPath.reset();
		mFlashPath.moveTo(flashStartXLeft, FLASH_START_Y);
		mFlashPath.lineTo(flashStartXRight, FLASH_START_Y);
		mFlashPath.lineTo(flashEndXRight, FLASH_END_Y);
		mFlashPath.lineTo(flashEndXLeft, FLASH_END_Y);
		mFlashPath.close();
		canvas.drawPath(mFlashPath, mFlashPaint);

		Bitmap emotionBitmap;
		if(lisenseEnable) {
			// draw Emotion
			emotionBitmap = getCurrentEmotionBitmap(lisenseEnable, mCurrentLevel);
		} else {
			emotionBitmap = isFlashOn? emotionLockedBitmaps[1]: emotionLockedBitmaps[0];
		}
		float emotionPosX = centerX - emotionBitmap.getWidth()/2;
		canvas.drawBitmap(emotionBitmap, emotionPosX, EMOTION_POS_Y, mFlashPaint);
	};
	
	private Bitmap getCurrentEmotionBitmap(boolean isLisenseEnable, int flashLevel) {
		Bitmap eyeBitmap;
		if(isLisenseEnable) {
			eyeBitmap = emotionBitmaps[flashLevel];
		} else {
			boolean isFlashOn = flashLevel > FlashController.LEVEL_OFF;
			eyeBitmap = isFlashOn? emotionLockedBitmaps[1]: emotionLockedBitmaps[0];
		}
		return eyeBitmap;
	}
	
	public void releaseData() {
		int sizeOfEmotion = emotionBitmaps != null? emotionBitmaps.length: 0;
		for(int i = 0; i < sizeOfEmotion; ++i) {
			emotionBitmaps[i].recycle();
		}
		
		int sizeOfEmotionLocked = emotionLockedBitmaps != null? emotionLockedBitmaps.length: 0;
		for(int i = 0; i < sizeOfEmotionLocked; ++i) {
			emotionLockedBitmaps[i].recycle();
		}
		
		if(flashOnBitmap != null) {
			flashOnBitmap.recycle();
		}
		
		if(flashOffBitmap != null) {
			flashOffBitmap.recycle();
		}
	}
} public class GuideViewManager implements OnClickListener , OnTouchListener{
	private WindowManager wm;
	private LayoutParams winParams;
	private Context appContext;
	private Timer timer = new Timer();
	private TimerTask autoCloseTask;
	private View mGuideView;
	
	public final static int AUTO_CLOSE_NOT_NEED = 0;
	private final static int AUTO_CLOSE_MSG = 1;
	private boolean closeAble;
	
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			if( msg.what == AUTO_CLOSE_MSG) {
				close();
			}
		};
	};

	public GuideViewManager(WindowManager wm, int windowType) {
		appContext = FlashApp.getContext();

		this.wm = wm;

		winParams = new LayoutParams();
		winParams.type = windowType;
		winParams.format = PixelFormat.RGBA_8888;
		winParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
				| LayoutParams.FLAG_NOT_FOCUSABLE
				| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
		winParams.windowAnimations = R.style.info_popu_anim;
	}
	
	public void add(View guideView, int gravity, int posX, int posY, boolean closeAble ) {
		add(guideView, gravity, posX, posY, 0, closeAble);
	}

	public void add(View guideView, int gravity, int posX, int posY, long autoCloseTimeDelay, boolean closeAble) {
		mGuideView = guideView;
		mGuideView.measure(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, 
				android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
		
		winParams.width = mGuideView.getMeasuredWidth();
		winParams.height = mGuideView.getMeasuredHeight();
		winParams.gravity = gravity;

		winParams.x = posX;
		winParams.y = posY;

		wm.addView(guideView, winParams);
		guideView.setOnTouchListener(this);
		guideView.setOnClickListener(this);
		
		if(autoCloseTimeDelay > 0) {
			autoCloseTask = new TimerTask() {
				
				@Override
				public void run() {
					handler.sendEmptyMessage(AUTO_CLOSE_MSG);
					autoCloseTask = null;
				}
			};
			timer.schedule(autoCloseTask, autoCloseTimeDelay);
		}
	}
	
	public void close() {
		if(autoCloseTask != null) {
			autoCloseTask.cancel();
		}
		if(mGuideView != null) {
			wm.removeView(mGuideView);
			mGuideView = null;
		}
	}

	@Override
	public void onClick(View view) {
		close();
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		boolean isHandled = false;
		if(event.getAction() == MotionEvent.ACTION_OUTSIDE) {
			close();
			isHandled = true;
		}
		return isHandled;
	}
} public interface OnFlashStateChangeListener {
	public void onSwitchClick();
	public void onSwitchTurnUp();
	public void onSwitchTurnDown();
}
import android.os.Bundle;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import com.hellodev.lightme.FlashController;
import com.hellodev.lightme.FlashController.OnFlashLevelChangedListener;
import com.hellodev.lightme.R;
import com.hellodev.lightme.service.ServiceHelper;
import com.hellodev.lightme.util.LightmeConstants;
import com.hellodev.lightme.util.MConnectHelper;
import com.hellodev.lightme.util.MDisplayHelper;
import com.hellodev.lightme.util.MLisenseMangaer;
import com.hellodev.lightme.util.MPreferenceManager;
import com.hellodev.lightme.util.SmartBarUtils;
import com.hellodev.lightme.util.MLisenseMangaer.OnLisenseStateChangeListener;
import com.hellodev.lightme.view.FlashView;
import com.hellodev.lightme.view.GuideViewManager;
import com.hellodev.lightme.view.OnFlashStateChangeListener;
import com.umeng.analytics.MobclickAgent;
package com.hellodev.lightme.activity;



public class MainActivity extends Activity implements
		OnFlashStateChangeListener, OnFlashLevelChangedListener,
		OnLisenseStateChangeListener, OnClickListener {
	private final static String TAG = "MainActivity";

	private FlashView flashView;