/* * Copyright (C) 2014 AChep@xda <artemchep@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package com.achep.acdisplay; import android.app.Notification; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.telephony.TelephonyManager; import android.util.Log; import com.achep.acdisplay.blacklist.Blacklist; import com.achep.acdisplay.notifications.NotificationPresenter; import com.achep.acdisplay.notifications.OpenNotification; import com.achep.acdisplay.services.activemode.sensors.ProximitySensor; import com.achep.acdisplay.ui.activities.AcDisplayActivity; import com.achep.acdisplay.ui.activities.KeyguardActivity; import com.achep.base.utils.Operator; import com.achep.base.utils.power.PowerUtils; import com.achep.base.utils.zen.ZenConsts; import com.achep.base.utils.zen.ZenUtils; import static com.achep.base.Build.DEBUG; /** * Created by Artem on 07.03.14. */ public class Presenter implements NotificationPresenter.OnNotificationPostedListener { private static final String TAG = "AcDisplayPresenter"; private static final String WAKE_LOCK_TAG = "AcDisplay launcher."; public static final int STATE_CREATED = 5; public static final int STATE_STARTED = 4; public static final int STATE_RESUMED = 3; public static final int STATE_PAUSED = 2; public static final int STATE_STOPPED = 1; public static final int STATE_DESTROYED = 0; private static Presenter sPresenter; @Nullable private AcDisplayActivity mActivity; private int mActivityState = STATE_DESTROYED; public static synchronized Presenter getInstance() { if (sPresenter == null) { sPresenter = new Presenter(); } return sPresenter; } /** * {@inheritDoc} */ @Override public void onNotificationPosted(@NonNull Context context, @NonNull OpenNotification n, int flags) { boolean silent = Operator.bitAnd(flags, NotificationPresenter.FLAG_SILENCE); if (!silent) tryStartGuiCauseNotification(context, n); } //-- START-UP ------------------------------------------------------------- /** * Checks if the current state of device is correct for waking-up cause * of notification, or no. */ public boolean checkNotification(@NonNull Context context, @NonNull OpenNotification n) { NotificationPresenter np = NotificationPresenter.getInstance(); if (np.isTestNotification(context, n)) { return true; // force test notification to be shown } if (ProximitySensor.isNear()) { // Don't display while device is face down. return false; } Config config = Config.getInstance(); if (!config.isEnabled() || !config.isNotifyWakingUp() // Inactive time || config.isInactiveTimeEnabled() && InactiveTimeHelper.isInactiveTime(config) // Only while charging || config.isEnabledOnlyWhileCharging() && !PowerUtils.isPlugged(context)) { // Don't turn screen on due to user settings. return false; } // Respect the device's zen mode. final int zenMode = ZenUtils.getValue(context); if (DEBUG) Log.d(TAG, "The current ZEN mode is " + ZenUtils.zenModeToString(zenMode)); switch (zenMode) { case ZenConsts.ZEN_MODE_IMPORTANT_INTERRUPTIONS: if (n.getNotification().priority >= Notification.PRIORITY_HIGH) { break; } case ZenConsts.ZEN_MODE_NO_INTERRUPTIONS: return false; } String packageName = n.getPackageName(); Blacklist blacklist = Blacklist.getInstance(); return !blacklist.getAppConfig(packageName).isRestricted(); } /** * Checks if the screen if off and call state is idle. */ public boolean checkBasics(@NonNull Context context) { TelephonyManager ts = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); return !PowerUtils.isScreenOn(context) && ts.getCallState() == TelephonyManager.CALL_STATE_IDLE; } public boolean tryStartGuiCauseNotification( @NonNull Context context, @NonNull OpenNotification n) { final int hash = n.hashCode(); return checkNotification(context, n) && checkBasics(context) && start(context, hash); } public boolean tryStartGuiCauseSensor(@NonNull Context context) { return checkBasics(context) && start(context); } //-- START-UP ------------------------------------------------------------- public boolean start(@NonNull Context context) { return start(context, 0); } public boolean start(@NonNull Context context, int notification) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); // Wake up from possible deep sleep. // // ))) // ((( // +-----+ // | |] // `-----' Good morning! ^-^ // ___________ // `---------' pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG).acquire(1000); //kill(); context.startActivity(new Intent(context, AcDisplayActivity.class) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_FROM_BACKGROUND) .putExtra(KeyguardActivity.EXTRA_CAUSE, notification) .putExtra(KeyguardActivity.EXTRA_TURN_SCREEN_ON, true)); if (DEBUG) Log.i(TAG, "Launching AcDisplay activity; state=" + mActivityState); return true; } public boolean tryStartGuiCauseKeyguard(@NonNull Context context) { if ((mActivityState == STATE_RESUMED || mActivityState == STATE_PAUSED) && !isFinishing()) { Log.i(TAG, "Passed the AcDisplay keyguard launch cause it\'s showing"); return true; } context.startActivity(new Intent(context, AcDisplayActivity.class) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION)); if (DEBUG) Log.i(TAG, "Launching[kg] AcDisplay activity; state=" + mActivityState); return true; } //-- ACTIVITY ------------------------------------------------------------- public void onCreate(@NonNull AcDisplayActivity activity) { mActivity = activity; mActivityState = STATE_CREATED; } public void onStart() { mActivityState = STATE_STARTED; } public void onResume() { mActivityState = STATE_RESUMED; } public void onPause() { mActivityState = STATE_PAUSED; } public void onStop() { mActivityState = STATE_STOPPED; } public void onDestroy() { mActivity = null; mActivityState = STATE_DESTROYED; } /** * @return {@code true} if the activity is present and finishing, * {@code false} otherwise. */ private boolean isFinishing() { return mActivity != null && mActivity.isFinishing(); } public boolean isLocked() { return mActivityState == STATE_RESUMED; } //-- OTHER ---------------------------------------------------------------- public void kill() { if (mActivity != null) mActivity.finish(); } }