/*
* 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.hooks;
import android.content.ComponentName;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import org.json.JSONArray;
import org.json.JSONObject;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.CLOSE_OBJECT_KEY;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.IMOD_RESET_ON_SCREEN_OFF;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.PACKAGE_HISTORY_ARRAY_KEY;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.PROCESS_HISTORY_ARRAY_KEY;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.getDefault;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.readFile;
import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.writeFile;
import static de.robv.android.xposed.XposedBridge.log;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
import static de.robv.android.xposed.XposedHelpers.setObjectField;
class SystemUI {
static final String PACKAGE_NAME = "com.android.systemui";
static final String PACKAGE_NAME_KEYGUARD = "com.android.keyguard";
private static final String HIDE_RECENTS_THUMBNAILS = "hide_recents_thumbnails";
private static final boolean LOLLIPOP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
static void init(final XSharedPreferences prefsApps, XC_LoadPackage.LoadPackageParam lPParam) {
try {
@ColorInt final int color = true ? Color.WHITE : Color.BLACK; // TODO
if (LOLLIPOP) {
findAndHookMethod(PACKAGE_NAME + ".recents.views.TaskViewThumbnail", lPParam.classLoader, "rebindToTask", PACKAGE_NAME + ".recents.model.Task", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
prefsApps.reload();
Object task = param.args[0];
String packageName = ((ComponentName) getObjectField(getObjectField(getObjectField(task, "key"), "mComponentNameKey"), "component")).getPackageName();
if (prefsApps.getBoolean(HIDE_RECENTS_THUMBNAILS, false) && prefsApps.getBoolean(packageName, false)) {
Bitmap replacement;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
replacement = Bitmap.createBitmap(new int[]{color}, 1, 1, Bitmap.Config.RGB_565);
} else {
Bitmap thumbnail = ((Bitmap) getObjectField(task, "thumbnail"));
replacement = Bitmap.createBitmap(thumbnail.getWidth(), thumbnail.getHeight(), Bitmap.Config.RGB_565);
replacement.eraseColor(color);
}
setObjectField(task, "thumbnail", replacement);
}
}
});
} else {
findAndHookMethod(PACKAGE_NAME + ".recent.TaskDescription", lPParam.classLoader, "getThumbnail", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
prefsApps.reload();
if (prefsApps.getBoolean(HIDE_RECENTS_THUMBNAILS, false) && prefsApps.getBoolean(getObjectField(param.thisObject, "packageName").toString(), false)) {
param.setResult(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? new ColorDrawable(color) : Bitmap.createBitmap(new int[]{color}, 1, 1, Bitmap.Config.RGB_565));
}
}
});
}
} catch (Throwable t) {
log(t);
}
}
static void initScreenOff(final XSharedPreferences prefsApps, final XC_LoadPackage.LoadPackageParam lPParam) {
// Resolve vars
String hookedClass;
try {
if (LOLLIPOP) throw new Error();
// Handle MIUI Keyguard class
XposedHelpers.findClass(PACKAGE_NAME_KEYGUARD + ".MiuiKeyguardViewMediator", lPParam.classLoader);
hookedClass = PACKAGE_NAME_KEYGUARD + ".MiuiKeyguardViewMediator";
log("ML: Recognized MIUI device.");
} catch (Error e) {
hookedClass = lPParam.packageName.replace(".keyguard", "") + ".keyguard.KeyguardViewMediator";
}
final XC_MethodHook hook = new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
prefsApps.reload();
if (prefsApps.getBoolean(IMOD_RESET_ON_SCREEN_OFF, false)) {
writeFile(getDefault());
log("ML: Screen turned off, locked apps.");
} else {
writeFile(readFile()
.put(PROCESS_HISTORY_ARRAY_KEY, new JSONArray())
.put(PACKAGE_HISTORY_ARRAY_KEY, new JSONArray())
.put(CLOSE_OBJECT_KEY, new JSONObject()));
}
}
};
// Hook
try {
findAndHookMethod(hookedClass, lPParam.classLoader, "onScreenTurnedOff", Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? new Object[]{hook} : new Object[]{int.class, hook});
} catch (Throwable t) {
log(t);
}
}
}