package com.aero.control.service;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.Service;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.view.Display;
import android.widget.Toast;
import com.aero.control.AeroActivity;
import com.aero.control.R;
import com.aero.control.helpers.PerApp.AppMonitor.AppContext;
import com.aero.control.helpers.PerApp.AppMonitor.AppLogger;
import com.aero.control.helpers.PerApp.AppMonitor.JobManager;
import com.aero.control.helpers.settingsHelper;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Created by Alexander Christ on 17.05.14.
*/
public final class PerAppService extends Service {
private static String mPreviousApp = null;
private static String mCurrentApp = null;
private static final String perAppProfileHandler = "perAppProfileHandler";
private boolean mActive;
private String mProfile;
private SharedPreferences mPerAppPrefs;
private ActivityManager mAm;
private Context mContext;
private static final settingsHelper settingsHelper = new settingsHelper();
private static final Handler mHandler = new Handler(Looper.getMainLooper());
private Runnable mRunnable;
private static JobManager mJobManager;
private final String mClassName = getClass().getName();
private boolean mShowToasts = true;
@Override
public void onCreate() {
final boolean enabled = (AeroActivity.perAppService != null) ? AeroActivity.perAppService.getState() : true;
mJobManager = JobManager.instance(PerAppService.this);
if (mContext == null)
mContext = this;
if (mRunnable == null) {
mRunnable = new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
// Do work in its own thread;
if (enabled) {
runTask();
}
mHandler.postDelayed(mRunnable, 5000);
}
});
}
};
}
new Thread(mRunnable).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void runTask() {
AppContext localContext = null;
if (mPerAppPrefs == null)
mPerAppPrefs = mContext.getSharedPreferences(perAppProfileHandler, Context.MODE_PRIVATE);
mShowToasts = PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean("per_app_toast", true);
// init our data;
setAppData();
if (mJobManager != null) {
mJobManager.setContext(mContext);
localContext = mJobManager.getAppContext(mCurrentApp);
mJobManager.setSleep(isScreenOn());
/*
* We need to check three things here before shutting down the JobManager;
* 1.) Is the context null, e.g. are we disabled or sleeping?
* 2.) Is the last known state NOT the sleeping state?
* 3.) Is the screen currently on?
*/
if (localContext == null && !mJobManager.getSleepState() && isScreenOn()) {
AppLogger.print(mClassName, "Shutting down JobManager...", 0);
mJobManager = null;
} else {
mJobManager.schedule(localContext);
}
AeroActivity.mJobManager = mJobManager;
}
// Check if our screen is on, if not, return;
if (isScreenOn()) {
return;
}
if (mPreviousApp != null && mCurrentApp != null) {
if (!(mPreviousApp.equals(mCurrentApp))) {
if(mActive) {
if (mShowToasts) {
Toast.makeText(mContext, mContext.getText(R.string.return_to_normal), Toast.LENGTH_LONG).show();
}
mActive = false;
mProfile = null;
settingsHelper.executeDefault();
}
final Map<String,?> keys = mPerAppPrefs.getAll();
for (final Map.Entry<String,?> entry : keys.entrySet()) {
final String savedSelectedProfiles = mPerAppPrefs.getString(entry.getKey(), null);
if (savedSelectedProfiles == null)
return;
final String tmp[] = savedSelectedProfiles.replace("+", " ").split(" ");
for (final String a : tmp) {
if (mCurrentApp.equals(a)) {
mProfile = entry.getKey();
if (mShowToasts) {
Toast.makeText(mContext, mContext.getText(R.string.apply_profile) + " " + mProfile, Toast.LENGTH_LONG).show();
}
mActive = true;
// Passing the profile to our settings helper;
settingsHelper.setSettings(mContext, mProfile, false);
}
}
}
}
else {
// No app change detected, return;
return;
}
}
}
private void setAppData() {
String PackageName = mCurrentApp;
mPreviousApp = PackageName;
if (mAm == null)
mAm = (ActivityManager) PerAppService.this.getSystemService(ACTIVITY_SERVICE);
// Get the first item in the list;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
PackageName = getTopApp();
} else {
ActivityManager.RunningTaskInfo AppInfo = mAm.getRunningTasks(1).get(0);
PackageName = AppInfo.topActivity.getPackageName();
}
if (PackageName != null) {
PackageName = PackageName.trim();
}
mCurrentApp = PackageName;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private String getTopApp() {
String visibleApp = null;
long time = System.currentTimeMillis();
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> sortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
sortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (!sortedMap.isEmpty()) {
// Get the last name;
visibleApp = sortedMap.get(sortedMap.lastKey()).getPackageName();
}
}
return visibleApp;
}
private boolean isScreenOn() {
// Take special care for API20+
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
DisplayManager dm = (DisplayManager) mContext.getSystemService(mContext.DISPLAY_SERVICE);
// We iterate through all available displays
for (Display display : dm.getDisplays()) {
if (display.getState() != Display.STATE_OFF)
return false;
}
// If we are here, all displays are on;
return true;
} else {
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
return !pm.isScreenOn();
}
}
}