/* * Copyright 2013 Yoshihiro Miyama * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.kyakujin.android.autoeco.eco; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import com.kyakujin.android.autoeco.Conf; import com.kyakujin.android.autoeco.Conf.EcoExecFrom; import com.kyakujin.android.autoeco.Conf.Priority; import com.kyakujin.android.autoeco.Logger; import com.kyakujin.android.autoeco.db.dao.EcoDAO; import com.kyakujin.android.autoeco.service.AutoEcoNotificationActivity; /** * 節電実行クラス */ /** * @author kyakujin * */ public class EcoExec { private final String TAG = Conf.APP_NAME + ":" + this.getClass().getSimpleName(); private static EcoExecFrom mFrom; private static int mId; private static State mState; private static Context mContext; private static Priority mPriority = Priority.BATTERY; private static boolean mBatterySrvEnabled; private static String mUpdateTime; private static boolean mIsOverThreathold; private static boolean mRollbackFlag = false; /** * State Pattern<br> * 節電実行の可否ルールをここで集約 */ public enum State { ON { /* (非 Javadoc) * @see com.kyakujin.android.autoeco.eco.EcoExec.State#start() */ @Override protected void start() { Logger.d(Conf.APP_NAME + this.getClass().getSimpleName(), "start Eco."); exec.doEco(); } @Override protected void stop() { /** DO NOTHING */ Logger.d(Conf.APP_NAME + this.getClass().getSimpleName(), "stop Eco."); } }, OFF { @Override protected void start() { Logger.d(Conf.APP_NAME + this.getClass().getSimpleName(), "start Eco."); exec.doEco(); } @Override protected void stop() { /** DO NOTHING */ Logger.d(Conf.APP_NAME + this.getClass().getSimpleName(), "DO NOTHING state:OFF"); } }, ON_BATTERY { @Override protected void start() { switch (mFrom) { case SCHED: // 以下を満たす場合はスキップする(つまり、バッテリーサービスによる節電実行を優先) // ・バッテリーサービスが稼働中 // ・プライオリティがバッテリーサービス // ・バッテリーレベルがしきい値を下回っている if (mBatterySrvEnabled && (mPriority == Priority.BATTERY) && !mIsOverThreathold) { // バッテリーサービス実行中の状態にロールバック mRollbackFlag = true; break; } exec.doEco(); break; case BATTERY: // 設定に変更がなければ EcoDAO dao = new EcoDAO(mContext); if (dao.getTimeStamp(mId, mFrom).equals(mUpdateTime)) break; exec.doEco(); break; case MANUAL: exec.doEco(); break; default: } } @Override protected void stop() { /** DO NOTHING */ Logger.d(Conf.APP_NAME + this.getClass().getSimpleName(), "stop Eco.(BATTERY_ON)"); } }; protected abstract void start(); protected abstract void stop(); } /** * 実行状態(以下のstate)を設定する。 * * @param state 実行状態 * ON: 実行済み * OFF: 停止済み * ON_BATTERY: バッテリー連動機能から実行済み */ private static void setState(State state) { mState = state; // プリファレンスに登録 SharedPreferences pref = mContext.getSharedPreferences(Conf.PREF, Context.MODE_PRIVATE); Editor e = pref.edit(); e.putInt(Conf.PREFKEY_ECOSTATE, state.ordinal()); e.commit(); Logger.d(Conf.APP_NAME + ":EcoExec", "set state=" + state.ordinal()); } /** * バッテリー連動機能からの実行済み状態へロールバックする。 */ private synchronized void rollbackToBattery() { Logger.d(Conf.APP_NAME + ":EcoExec", "ROLLBACK!"); SharedPreferences pref = mContext.getSharedPreferences(Conf.PREF, Context.MODE_PRIVATE); Editor e = pref.edit(); e.putInt(Conf.PREFKEY_ECOSTATE, State.ON_BATTERY.ordinal()); e.putInt(Conf.PREFKEY_LAST_ECOFROM, EcoExecFrom.BATTERY.ordinal()); EcoDAO dao = new EcoDAO(mContext); e.putString(Conf.PREFKEY_UPDATE_TIME, dao.getTimeStamp(1, EcoExecFrom.BATTERY)); e.commit(); } /** * スケジュール、バッテリー連動、マニュアルのどれから実行されたか記録する。 */ private synchronized void savePref() { // どこからECO実行命令がきたかプリファレンスに登録 SharedPreferences pref = mContext.getSharedPreferences(Conf.PREF, Context.MODE_PRIVATE); Editor e = pref.edit(); e.putInt(Conf.PREFKEY_LAST_ECOFROM, mFrom.ordinal()); Logger.d(Conf.APP_NAME + ":EcoExec", "last executed by shced or battry=" + mFrom.ordinal()); EcoDAO dao = new EcoDAO(mContext); Logger.d(Conf.APP_NAME + ":EcoExec", "DB: eco modified time=" + dao.getTimeStamp(mId, mFrom)); e.putString(Conf.PREFKEY_UPDATE_TIME, dao.getTimeStamp(mId, mFrom)); e.commit(); } /** * 節電実行のキックメソッド。 * @param id 実行対象のecoId */ public synchronized void startEco(int id) { mId = id; State state = State.ON; switch (mFrom) { case SCHED: case MANUAL: Logger.d(Conf.APP_NAME + ":EcoExec", "MANUAL CLICK!"); state = State.ON; break; case BATTERY: state = State.ON_BATTERY; break; default: state = State.ON; } mState.start(); setState(state); savePref(); if (mRollbackFlag) { rollbackToBattery(); mRollbackFlag = false; } } /** * 節電実行を停止状態にする。 */ public synchronized void stopEco() { mState.stop(); setState(State.OFF); savePref(); } // Singleton Pattern private static EcoExec exec = new EcoExec(); private EcoExec() { } /** * このクラスのインスタンスを返却。 * @param context アプリケーションコンテキスト * @param from どの機能から実行指示がきたか * @return exec このクラスのインスタンス */ public synchronized static EcoExec getInstance(Context context, EcoExecFrom from) { mFrom = from; mContext = context; // ECO実行状態を取得 SharedPreferences pref = mContext.getSharedPreferences(Conf.PREF, Context.MODE_PRIVATE); Logger.d( Conf.APP_NAME + ":EcoExec", "getInstance current state=" + pref.getInt(Conf.PREFKEY_ECOSTATE, State.ON.ordinal())); State[] values = State.values(); setState(values[pref.getInt(Conf.PREFKEY_ECOSTATE, State.ON.ordinal())]); // バッテリーサービス有効化状態を取得 mBatterySrvEnabled = (pref.getInt(Conf.PREFKEY_BATTERYSRV_ENABLED, 0) == 1 ? true : false); // バッテリーレベルがしきい値を上回っているか取得 mIsOverThreathold = (pref.getInt(Conf.PREFKEY_BATTERY_LEVEL, 0) == 1 ? true : false); // 前回節電実行時のアップデート時間を取得 mUpdateTime = pref.getString(Conf.PREFKEY_UPDATE_TIME, ""); Logger.d(Conf.APP_NAME + ":EcoExec", "PREF: eco update time=" + mUpdateTime); return exec; } /** * 節電を実行する。 */ private void doEco() { Intent notification = new Intent(mContext, AutoEcoNotificationActivity.class); // 画面を起動するためにはこれが必要 notification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); notification.putExtra(Conf.SHARED_EXTRA_ID, mId); notification.putExtra(Conf.SHARED_EXTRA_FROM, mFrom.ordinal()); mContext.startActivity(notification); } }