/* * MaxLock, an Xposed applock module for Android * Copyright (C) 2014-2016 Max Rumpf alias Maxr1998 * * 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 3 of the License, or 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, see <http://www.gnu.org/licenses/>. */ package de.Maxr1998.xposed.maxlock.util; import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import de.Maxr1998.xposed.maxlock.Common; import de.Maxr1998.xposed.maxlock.no_xposed.AppLockService; import de.robv.android.xposed.XposedBridge; public final class AppLockHelpers { public static final String PROCESS_HISTORY_ARRAY_KEY = "procs"; public static final String PACKAGE_HISTORY_ARRAY_KEY = "pkgs"; public static final int UNLOCK_ID = -0x3A8; public static final String IMOD_OBJECT_KEY = "iModPerApp"; public static final String CLOSE_OBJECT_KEY = "close"; public static final String IMOD_LAST_UNLOCK_GLOBAL = "IMoDGlobalDelayTimer"; public static final String IMOD_RESET_ON_SCREEN_OFF = "reset_imod_screen_off"; @SuppressLint("SdCardPath") private static final String HISTORY_PATH = "/data/data/" + Common.MAXLOCK_PACKAGE_NAME + "/files/history.json"; private static final String IMOD_DELAY_APP = "delay_inputperapp"; private static final String IMOD_DELAY_GLOBAL = "delay_inputgeneral"; private AppLockHelpers() { } public static boolean pass(int taskId, @NonNull String packageName, @Nullable String activityName, @NonNull JSONObject history, @NonNull SharedPreferences prefs) throws Throwable { writeFile(addToHistory(taskId, packageName, history)); // MasterSwitch disabled if (!prefs.getBoolean(Common.MASTER_SWITCH_ON, true)) { return true; } // Activity got launched/closed if (history.getJSONArray(PROCESS_HISTORY_ARRAY_KEY).optInt(1) == UNLOCK_ID) { return true; } // Activity not locked if (activityName != null && !prefs.getBoolean(activityName, true)) { return true; } // I.Mod active boolean iModDelayGlobalEnabled = prefs.getBoolean(Common.ENABLE_IMOD_DELAY_GLOBAL, false); boolean iModDelayAppEnabled = prefs.getBoolean(Common.ENABLE_IMOD_DELAY_APP, false); long iModLastUnlockGlobal = history.optLong(IMOD_LAST_UNLOCK_GLOBAL); JSONObject iModPerApp = history.optJSONObject(IMOD_OBJECT_KEY); long iModLastUnlockApp = 0; if (iModPerApp != null) { iModLastUnlockApp = iModPerApp.optLong(packageName); } return (iModDelayGlobalEnabled && (iModLastUnlockGlobal != 0 && System.currentTimeMillis() - iModLastUnlockGlobal <= prefs.getInt(IMOD_DELAY_GLOBAL, 600000))) || iModDelayAppEnabled && (iModLastUnlockApp != 0 && System.currentTimeMillis() - iModLastUnlockApp <= prefs.getInt(IMOD_DELAY_APP, 600000)); } public static boolean close(JSONObject history, String packageName) { JSONObject close = history.optJSONObject(CLOSE_OBJECT_KEY); return close != null && System.currentTimeMillis() - close.optLong(packageName) <= 800; } public static JSONObject getDefault() throws JSONException { JSONObject history = new JSONObject(); JSONArray procs = new JSONArray(); JSONArray pkgs = new JSONArray(); JSONObject iMod = new JSONObject(); JSONObject close = new JSONObject(); history.put(PROCESS_HISTORY_ARRAY_KEY, procs) .put(PACKAGE_HISTORY_ARRAY_KEY, pkgs) .put(IMOD_OBJECT_KEY, iMod) .put(CLOSE_OBJECT_KEY, close); return history; } public static JSONObject readFile() throws JSONException { JSONObject history; try { BufferedReader reader = new BufferedReader(new FileReader(HISTORY_PATH), 50); String json = reader.readLine(); reader.close(); try { history = new JSONObject(json); } catch (JSONException | NullPointerException e) { return getDefault(); } if (!(history.has(PROCESS_HISTORY_ARRAY_KEY) && history.has(PACKAGE_HISTORY_ARRAY_KEY) && history.has(IMOD_OBJECT_KEY) && history.has(CLOSE_OBJECT_KEY))) { return getDefault(); } } catch (IOException e) { log("ML: File not found or reading error: " + e.getLocalizedMessage()); return getDefault(); } return history; } public static void writeFile(@NonNull JSONObject history) throws JSONException { try { File JSONFile = new File(HISTORY_PATH); if (!JSONFile.exists()) { throw new FileNotFoundException("File could not be written, as it doesn't exist."); } FileWriter bw = new FileWriter(HISTORY_PATH); bw.write(history.toString()); bw.close(); } catch (IOException e) { e.printStackTrace(); } } public static JSONObject addToHistory(int taskId, String packageName, JSONObject history) throws JSONException { JSONArray procs = history.optJSONArray(PROCESS_HISTORY_ARRAY_KEY); JSONArray pkgs = history.optJSONArray(PACKAGE_HISTORY_ARRAY_KEY); // Only add task id if new task got launched or if we are in legacy mode anyway if (taskId != procs.optInt(0) || taskId == -1) { // If new task doesn't have same package name, keep (shift back) the previous task id if (!packageName.equals(pkgs.optString(0))) { procs.put(1, procs.optInt(0)); } procs.put(0, taskId); } // Shift back package names pkgs.put(2, pkgs.optString(1)).put(1, pkgs.optString(0)).put(0, packageName); history.put(PROCESS_HISTORY_ARRAY_KEY, procs).put(PACKAGE_HISTORY_ARRAY_KEY, pkgs); return history; } public static void log(String text) { try { XposedBridge.log(text); } catch (Exception e) { Log.d(AppLockService.TAG, text); } } }