Android 15.0 启动app时设置密码锁(升级到framework层判断)
framework层判断包名是否加锁,如果加锁了,启动systemui的输入密码的activity,验证通过后,继续启动activity
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/AndroidManifest.xml b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/AndroidManifest.xml
index e7cc18748d9..f5063022ca0 100644
--- a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/AndroidManifest.xml
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/AndroidManifest.xml
@@ -1119,5 +1119,13 @@android:showForAllUsers="true"android:theme="@style/ShortcutHelperTheme"android:excludeFromRecents="true" />
+
+ <activity android:name=".lock.PasswordVerifyActivity"
+ android:exported="true"
+ android:theme="@android:style/Theme.DeviceDefault.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:taskAffinity=""
+ android:launchMode="singleTask">
+ </activity></application></manifest>
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6859d55c16c..73d7b143843 100644
--- a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1404,4 +1404,13 @@<string name="text_both">两者</string><string name="title_input_joystick_switch">启用虚拟摇杆</string>
+
+ <string name="verify_title">请输入密码</string>
+ <string name="verify_message">应用 <xliff:g name="pkg">%1$s</xliff:g> 已被锁定</string>
+ <string name="verify_button">验证</string>
+ <string name="verify_cancel">取消</string>
+ <string name="verify_success">验证成功</string>
+ <string name="verify_failed">密码错误,请重试</string>
+ <string name="verify_cancelled">已取消验证</string>
+</resources>
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values/strings.xml b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values/strings.xml
index 433983d0619..9b630b537bc 100644
--- a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values/strings.xml
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/res/values/strings.xml
@@ -3669,4 +3669,12 @@<string name="text_both">Both</string><string name="title_input_joystick_switch">Enable virtual joystick</string>
+
+ <string name="verify_title">Enter Password</string>
+ <string name="verify_message">App <xliff:g name="pkg">%1$s</xliff:g> is locked</string>
+ <string name="verify_button">Verify</string>
+ <string name="verify_cancel">Cancel</string>
+ <string name="verify_success">Verification succeeded</string>
+ <string name="verify_failed">Incorrect password, try again</string>
+ <string name="verify_cancelled">Verification cancelled</string></resources>
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/src/com/android/systemui/lock/PasswordVerifyActivity.java b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/src/com/android/systemui/lock/PasswordVerifyActivity.java
new file mode 100644
index 00000000000..8891b31bb79
--- /dev/null
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/packages/SystemUI/src/com/android/systemui/lock/PasswordVerifyActivity.java
@@ -0,0 +1,105 @@
+package com.android.systemui.lock;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.text.InputType;
+import android.widget.EditText;
+import android.widget.Toast;
+import com.android.systemui.R;
+import android.util.Log;
+import java.util.List;
+import android.provider.Settings;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+
+
+public class PasswordVerifyActivity extends Activity {
+
+ private String lockedPackage;
+ private static final String PASSWORD_KEY = "persist.sys.lock_app.setting.password";
+ private static final String DEFAULT_PASSWORD = "soft1024";
+ private static final String TAG = "zdx_pwd_verify";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Log.d(TAG, "onCreate, pid=" + android.os.Process.myPid());
+
+ lockedPackage = getIntent().getStringExtra("locked_package");
+ if (lockedPackage == null || lockedPackage.isEmpty()) {
+ Toast.makeText(this, "No package specified", Toast.LENGTH_SHORT).show();
+ // Log.e(TAG, "lockedPackage is null or empty, finishing...");
+ finish();
+ return;
+ }
+
+
+ showPasswordDialog();
+ }
+
+ private void showPasswordDialog() {
+ EditText input = new EditText(this);
+ input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+
+
+
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.verify_title)
+ .setMessage(getString(R.string.verify_message, ""))
+ .setView(input)
+ .setCancelable(false)
+ .setPositiveButton(R.string.verify_button, (dialog, which) -> {
+ String inputPassword = input.getText().toString();
+ String correctPassword = SystemProperties.get(PASSWORD_KEY, DEFAULT_PASSWORD);
+
+ // Log.d(TAG, "User entered password: " + inputPassword);
+
+ if (correctPassword.equals(inputPassword)) {
+ // Log.d(TAG, "Password correct. Saving timestamp for " + lockedPackage);
+ long now = System.currentTimeMillis();
+ boolean result = Settings.Secure.putLong(
+ getContentResolver(),
+ "lock_app_last_verified_" + lockedPackage,
+ now
+ );
+ // Log.d(TAG, "Timestamp saved: " + now + ", success=" + result);
+ Toast.makeText(this, R.string.verify_success, Toast.LENGTH_SHORT).show();
+
+ launchTargetApp(lockedPackage);
+ finish();
+ } else {
+ Toast.makeText(this, R.string.verify_failed, Toast.LENGTH_SHORT).show();
+ showPasswordDialog(); // retry
+ }
+ })
+ .setNegativeButton(R.string.verify_cancel, (dialog, which) -> {
+ Toast.makeText(this, R.string.verify_cancelled, Toast.LENGTH_SHORT).show();
+ finish();
+ })
+ .show();
+ }
+
+ private void launchTargetApp(String packageName) {
+ // Log.d(TAG, "launchTargetApp: " + packageName);
+ PackageManager pm = getPackageManager();
+ Intent intent = pm.getLaunchIntentForPackage(packageName);
+ if (intent != null) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // Log.d(TAG, "Launching intent: " + intent);
+ startActivity(intent);
+ } else {
+ // Log.e(TAG, "Unable to get launch intent for " + packageName);
+ Toast.makeText(this, "Unable to launch " + packageName, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+}
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java b/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
index 2ef876d16c5..a38bc89e096 100644
--- a/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -149,6 +149,14 @@ import java.lang.annotation.RetentionPolicy;import java.text.DateFormat;import java.util.Date;+
+import android.content.Intent;
+import android.content.ComponentName;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.os.SystemProperties;
+import android.content.SharedPreferences;/*** Controller for interpreting how and then launching an activity.*
@@ -161,6 +169,7 @@ class ActivityStarter {private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
+ private static final String LOCK_APP_ENABLE_KEY = "persist.sys.lock_app.enabled";private static final int INVALID_LAUNCH_MODE = -1;@@ -1504,6 +1513,29 @@ class ActivityStarter {: (customCallingUid >= 0 ? customCallingUid : actualCallingUid);}+ private boolean isAppLocked(String pkg) {
+ boolean isLockEnabled = SystemProperties.getBoolean(LOCK_APP_ENABLE_KEY, false);
+ if (!isLockEnabled) return false;
+ String locked_apps = android.provider.Settings.Secure.getString(mService.mContext.getContentResolver(), "locked_apps");
+ Slog.i(TAG, "locked app = " + locked_apps);
+ return locked_apps != null && java.util.Arrays.asList(locked_apps.split(",")).contains(pkg);
+ }
+
+ private boolean isPasswordPassedRecently(String pkg) {
+ long lastTime = Settings.Secure.getLong(mService.mContext.getContentResolver(),"lock_app_last_verified_" + pkg, 0L);
+ boolean recentlyPassed = System.currentTimeMillis() - lastTime < 2 * 60 * 60 * 1000; // 2小时
+ return recentlyPassed;
+ }
+
+ private void launchPasswordVerifyActivity(int userId, String pkg) {
+ android.content.Intent intent = new android.content.Intent();
+ intent.setComponent(new android.content.ComponentName(
+ "com.android.systemui", "com.android.systemui.lock.PasswordVerifyActivity"));
+ intent.putExtra("locked_package", pkg);
+ intent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
+ mService.mContext.startActivityAsUser(intent, android.os.UserHandle.of(userId));
+ }
+/*** Start an activity while most of preliminary checks has been done and caller has been* confirmed that holds necessary permissions to do so.
@@ -1518,6 +1550,15 @@ class ActivityStarter {int result = START_CANCELED;final Task startedActivityRootTask;+ // === App Lock Check Start ===
+ // 判断app 包名是否已经锁定
+ // Slog.e(TAG, " startActivityUnchecked r.packageName = "+ r.packageName );
+ if (r != null && isAppLocked(r.packageName) && !isPasswordPassedRecently(r.packageName)) {
+ launchPasswordVerifyActivity(r.mUserId, r.packageName);
+ return START_SUCCESS;
+ }
+ // === App Lock Check End ===
+// Create a transition now to record the original intent of actions taken within// startActivityInner. Otherwise, logic in startActivityInner could start a different// transition based on a sub-action.
diff --git a/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 892da04a4e4..3e6355c5428 100644
--- a/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/LA.QSSI.15.0_MC9452/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -173,6 +173,14 @@ import java.util.function.Predicate;import java.util.Arrays;import android.os.AsyncTask;+import android.content.Intent;
+import android.content.ComponentName;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.os.SystemProperties;
+import android.content.SharedPreferences;
+import vendor.qti.hardware.servicetracker.V1_2.IServicetracker;// TODO: This class has become a dumping ground. Let's
@@ -188,6 +196,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {private static final String TAG_ROOT_TASK = TAG + POSTFIX_ROOT_TASK;private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ private static final String LOCK_APP_ENABLE_KEY = "persist.sys.lock_app.enabled";/** How long we wait until giving up on the last activity telling us it is idle. */private static final int IDLE_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
@@ -2876,6 +2885,31 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {}}+
+ private boolean isAppLocked(String pkg) {
+ boolean isLockEnabled = SystemProperties.getBoolean(LOCK_APP_ENABLE_KEY, false);
+ if (!isLockEnabled) return false;
+ String locked_apps = android.provider.Settings.Secure.getString(mService.mContext.getContentResolver(), "locked_apps");
+ Slog.i(TAG, "locked app = " + locked_apps);
+ return locked_apps != null && java.util.Arrays.asList(locked_apps.split(",")).contains(pkg);
+ }
+
+ private boolean isPasswordPassedRecently(String pkg) {
+ long lastTime = Settings.Secure.getLong(mService.mContext.getContentResolver(),"lock_app_last_verified_" + pkg, 0L);
+ boolean recentlyPassed = System.currentTimeMillis() - lastTime < 2 * 60 * 60 * 1000; // 2小时
+ return recentlyPassed;
+ }
+
+ private void launchPasswordVerifyActivity(int userId, String pkg) {
+ android.content.Intent intent = new android.content.Intent();
+ intent.setComponent(new android.content.ComponentName(
+ "com.android.systemui", "com.android.systemui.lock.PasswordVerifyActivity"));
+ intent.putExtra("locked_package", pkg);
+ intent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
+ mService.mContext.startActivityAsUser(intent, android.os.UserHandle.of(userId));
+ }
+
+/*** Start the given task from the recent tasks. Do not hold WM global lock when calling this* method to avoid potential deadlock or permission deny by UriGrantsManager when resolving
@@ -2927,6 +2961,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {"startActivityFromRecents: Task " + taskId + " not found.");}+ final ActivityRecord rootActivity = task.getRootActivity();
+ if (rootActivity != null) {
+ String packageName = rootActivity.packageName;
+ // 判断app 包名是否已经锁定
+ if ( isAppLocked(packageName) && !isPasswordPassedRecently(packageName)) {
+ launchPasswordVerifyActivity(rootActivity.mUserId, packageName);
+ return 0;
+ }
+ }
+if (moveHomeTaskForward) {// We always want to return to the home activity instead of the recents// activity from whatever is started from the recents activity, so move
diff --git a/LA.QSSI.15.0_MC9452/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java b/LA.QSSI.15.0_MC9452/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
index a6a8d193ba6..02ab1f65978 100644
--- a/LA.QSSI.15.0_MC9452/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
+++ b/LA.QSSI.15.0_MC9452/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
@@ -2217,36 +2217,36 @@ public class Launcher extends StatefulActivity<LauncherState>// TODO:升级到framework层进行加锁app的判断
- boolean isLockEnabled = SystemProperties.getBoolean("persist.sys.lock_app.enabled", false);
- if (isLockEnabled){
- String app_list = getLockedAppList();
-
- ComponentName component = intent.getComponent();
- String packageName = component != null ? component.getPackageName() : "";
-
- if (!packageName.isEmpty()) {
- List<String> lockedApps = Arrays.asList(app_list.split(","));
- if (lockedApps.contains(packageName)) {
- long now = System.currentTimeMillis();
- Long lastSuccessTime = mPasswordPassedMap.get(packageName);
- if (lastSuccessTime != null && (now - lastSuccessTime < PASSWORD_VALID_DURATION_MS)) {
- // 最近已通过密码验证,直接启动
- return super.startActivitySafely(v, intent, item);
- }
-
- // 否则弹出密码输入框
- showPasswordDialog(() -> {
- mPasswordPassedMap.put(packageName, System.currentTimeMillis());
- try {
- super.startActivity(intent, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- });
- return null;
- }
- }
- }
+ // boolean isLockEnabled = SystemProperties.getBoolean("persist.sys.lock_app.enabled", false);
+ // if (isLockEnabled){
+ // String app_list = getLockedAppList();
+
+ // ComponentName component = intent.getComponent();
+ // String packageName = component != null ? component.getPackageName() : "";
+
+ // if (!packageName.isEmpty()) {
+ // List<String> lockedApps = Arrays.asList(app_list.split(","));
+ // if (lockedApps.contains(packageName)) {
+ // long now = System.currentTimeMillis();
+ // Long lastSuccessTime = mPasswordPassedMap.get(packageName);
+ // if (lastSuccessTime != null && (now - lastSuccessTime < PASSWORD_VALID_DURATION_MS)) {
+ // // 最近已通过密码验证,直接启动
+ // return super.startActivitySafely(v, intent, item);
+ // }
+
+ // // 否则弹出密码输入框
+ // showPasswordDialog(() -> {
+ // mPasswordPassedMap.put(packageName, System.currentTimeMillis());
+ // try {
+ // super.startActivity(intent, null);
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // }
+ // });
+ // return null;
+ // }
+ // }
+ // }if (!hasBeenResumed()) {RunnableList result = new RunnableList();