/* * 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.ui; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.Keep; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatDelegate; import android.text.InputType; import android.util.Log; import android.view.ViewGroup; import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.Toast; import org.json.JSONException; import org.json.JSONObject; import de.Maxr1998.xposed.maxlock.Common; import de.Maxr1998.xposed.maxlock.R; import de.Maxr1998.xposed.maxlock.ui.lockscreen.LockView; import de.Maxr1998.xposed.maxlock.util.AppLockHelpers; import de.Maxr1998.xposed.maxlock.util.AuthenticationSucceededListener; import de.Maxr1998.xposed.maxlock.util.NotificationHelper; import de.Maxr1998.xposed.maxlock.util.Util; import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.CLOSE_OBJECT_KEY; import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.addToHistory; import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.readFile; import static de.Maxr1998.xposed.maxlock.util.AppLockHelpers.writeFile; public class LockActivity extends AppCompatActivity implements AuthenticationSucceededListener { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } private SharedPreferences prefs; @Keep private String[] names; private boolean unlocked = false; private AlertDialog fakeDieDialog, reportDialog; @Override protected void onCreate(Bundle savedInstanceState) { prefs = PreferenceManager.getDefaultSharedPreferences(this); final String lockActivityMode = getIntent().getStringExtra(Common.LOCK_ACTIVITY_MODE); final boolean fakeCrash = (lockActivityMode != null && lockActivityMode.equals(Common.MODE_FAKE_CRASH)) || (prefs.getBoolean(Common.ENABLE_FAKE_CRASH_ALL_APPS, false) && (lockActivityMode == null || !lockActivityMode.equals(Common.MODE_UNLOCK))); if (!fakeCrash) { if (prefs.getBoolean(Common.HIDE_STATUS_BAR, false)) { setTheme(R.style.TranslucentStatusBar_Full); } else { setTheme(R.style.TranslucentStatusBar); } } else { setTheme(R.style.FakeDieDialog); getWindow().setBackgroundDrawable(new ColorDrawable(0)); } super.onCreate(savedInstanceState); // Intent extras names = getIntent().getStringArrayExtra(Common.INTENT_EXTRAS_NAMES); if (names == null) { names = new String[]{"", ""}; Toast.makeText(this, "There was an error in the LockActivity, did you reboot after update?", Toast.LENGTH_LONG).show(); } if (!fakeCrash) { defaultSetup(); } else { fakeDieSetup(); } } private void defaultSetup() { // Authentication fragment/UI setContentView(new LockView(LockView.getThemedContext(this), names[0], names[1]), new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } private void fakeDieSetup() { PackageManager pm = getPackageManager(); ApplicationInfo requestPkgInfo; try { requestPkgInfo = pm.getApplicationInfo(names[0], 0); } catch (PackageManager.NameNotFoundException e) { requestPkgInfo = null; } String requestPkgFullName = (String) (requestPkgInfo != null ? pm.getApplicationLabel(requestPkgInfo) : "(unknown)"); AlertDialog.Builder fakeDieDialogBuilder = new AlertDialog.Builder(this); fakeDieDialog = fakeDieDialogBuilder.setMessage(String.format(getResources().getString(R.string.dialog_text_fake_die_stopped), requestPkgFullName)) .setNeutralButton(R.string.dialog_button_report, (dialogInterface, i) -> { if (prefs.getBoolean(Common.ENABLE_DIRECT_UNLOCK, false)) { fakeDieDialog.dismiss(); launchLockView(); finish(); } else { fakeDieDialog.dismiss(); final EditText input = new EditText(LockActivity.this); input.setMinLines(2); input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE); AlertDialog.Builder reportDialogBuilder = new AlertDialog.Builder(LockActivity.this); reportDialog = reportDialogBuilder.setView(input) .setTitle(R.string.dialog_title_report_problem) .setPositiveButton(android.R.string.ok, (dialogInterface1, i1) -> { if (input.getText().toString().equals(prefs.getString(Common.FAKE_CRASH_INPUT, "start"))) { reportDialog.dismiss(); launchLockView(); finish(); } else { Toast.makeText(LockActivity.this, "Thanks for your feedback", Toast.LENGTH_SHORT).show(); onBackPressed(); } }) .setNegativeButton(android.R.string.cancel, (dialogInterface12, i12) -> onBackPressed()) .setOnCancelListener(dialogInterface13 -> onBackPressed()) .create(); reportDialog.show(); } }) .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> onBackPressed()) .setOnCancelListener(dialogInterface -> onBackPressed()) .create(); fakeDieDialog.show(); } private void launchLockView() { Intent it = new Intent(this, LockActivity.class); it.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); it.putExtra(Common.LOCK_ACTIVITY_MODE, Common.MODE_UNLOCK); it.putExtra(Common.INTENT_EXTRAS_NAMES, names); startActivity(it); } @Override public void onAuthenticationSucceeded() { try { JSONObject history = readFile(); addToHistory(AppLockHelpers.UNLOCK_ID, Common.MAXLOCK_PACKAGE_NAME, history); history.put(AppLockHelpers.IMOD_LAST_UNLOCK_GLOBAL, System.currentTimeMillis()); history.optJSONObject(AppLockHelpers.IMOD_OBJECT_KEY).put(names[0], System.currentTimeMillis()); writeFile(history); } catch (JSONException e) { e.printStackTrace(); } unlocked = true; NotificationHelper.postIModNotification(this); finish(); overridePendingTransition(0, R.anim.lockscreen_fade_out_fast); } @Override public void onBackPressed() { Log.d(Util.LOG_TAG_LOCKSCREEN, "Pressed back."); try { JSONObject history = readFile(); history.optJSONObject(CLOSE_OBJECT_KEY).put(names[0], System.currentTimeMillis()); writeFile(history); } catch (JSONException e) { e.printStackTrace(); } super.onBackPressed(); } @Override public void onPause() { super.onPause(); if (fakeDieDialog != null) { fakeDieDialog.dismiss(); } else if (reportDialog != null) { reportDialog.dismiss(); } } @Override protected void onStop() { if (prefs.getBoolean(Common.ENABLE_LOGGING, false) && !unlocked) { Util.logFailedAuthentication(this, names[0]); } super.onStop(); } }