package com.achep.base.utils.power;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import com.achep.acdisplay.Atomic;
import com.achep.base.Device;
import com.achep.base.interfaces.IPowerSave;
import com.achep.base.interfaces.ISubscriptable;
import java.util.ArrayList;
import static com.achep.base.Build.DEBUG_POWER_SAVING;
/**
* @author Artem Chepurnoy
*/
public abstract class PowerSaveDetector implements
ISubscriptable<PowerSaveDetector.OnPowerSaveChanged>,
IPowerSave {
private static boolean sPowerSaveMode;
@NonNull
public static PowerSaveDetector newInstance(@NonNull Context context) {
return Device.hasLollipopApi()
? new PowerSaveLollipop(context)
: new PowerSaveCompat(context);
}
/**
* Returns {@code true} if the device is currently in power save mode.
* When in this mode, applications should reduce their functionality
* in order to conserve battery as much as possible.
*
* @return {@code true} if the device is currently in power save mode, {@code false} otherwise.
*/
public static boolean isPowerSaving() {
return sPowerSaveMode;
}
/**
* Inverse function to {@link #isPowerSaveMode()}
*/
/*
* I hate using `if (!...)` construction so this
* method was created
*/
public static boolean isNotPowerSaving() {
return !isPowerSaving();
}
protected final ArrayList<OnPowerSaveChanged> mListeners;
protected final Context mContext;
protected boolean mPowerSaveMode;
/**
* @author Artem Chepurnoy
*/
public interface OnPowerSaveChanged {
void onPowerSaveChanged(boolean powerSaving);
}
private PowerSaveDetector(@NonNull Context context) {
mListeners = new ArrayList<>();
mContext = context;
}
/**
* {@inheritDoc}
*/
@Override
public void registerListener(@NonNull OnPowerSaveChanged listener) {
mListeners.add(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void unregisterListener(@NonNull OnPowerSaveChanged listener) {
mListeners.remove(listener);
}
public abstract void start();
public abstract void stop();
/**
* {@inheritDoc}
*/
@Override
public boolean isPowerSaveMode() {
return mPowerSaveMode;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isNotPowerSaveMode() {
return !isNotPowerSaving();
}
protected void setPowerSaveMode(boolean psm) {
if (DEBUG_POWER_SAVING) psm = true;
if (mPowerSaveMode == psm) return;
sPowerSaveMode = mPowerSaveMode = psm;
notifyListeners();
}
private void notifyListeners() {
for (OnPowerSaveChanged listener : mListeners) {
listener.onPowerSaveChanged(mPowerSaveMode);
}
}
/**
* @author Artem Chepurnoy
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static class PowerSaveLollipop extends PowerSaveDetector {
private final PowerManager mPowerManager;
private final BroadcastReceiver mReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
setPowerSaveMode(mPowerManager.isPowerSaveMode());
break;
}
}
};
@NonNull
private final Atomic mAtomic = new Atomic(new Atomic.Callback() {
@Override
public void onStart(Object... objects) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
setPowerSaveMode(mPowerManager.isPowerSaveMode());
}
@Override
public void onStop(Object... objects) {
mContext.unregisterReceiver(mReceiver);
}
});
public PowerSaveLollipop(@NonNull Context context) {
super(context);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
}
@Override
public void start() {
mAtomic.start();
}
@Override
public void stop() {
mAtomic.stop();
}
}
/**
* @author Artem Chepurnoy
*/
private static class PowerSaveCompat extends PowerSaveDetector {
public PowerSaveCompat(@NonNull Context context) {
super(context);
}
@Override
public void start() { /* empty */ }
@Override
public void stop() { /* empty */ }
}
}