summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/LockTaskController.java61
-rw-r--r--services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java47
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java10
3 files changed, 109 insertions, 9 deletions
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index d77e1a20e0c0..ba3e25aea66c 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -22,8 +22,10 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
+import static android.content.Intent.ACTION_CALL_EMERGENCY;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
+import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
@@ -45,6 +47,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
@@ -52,9 +55,11 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
+import android.telecom.TelecomManager;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
@@ -133,6 +138,8 @@ public class LockTaskController {
WindowManagerService mWindowManager;
@VisibleForTesting
LockPatternUtils mLockPatternUtils;
+ @VisibleForTesting
+ TelecomManager mTelecomManager;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -165,7 +172,7 @@ public class LockTaskController {
/**
* Features that are allowed by DPC to show during LockTask mode.
*/
- private final SparseArray<Integer> mLockTaskFeatures = new SparseArray<>();
+ private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
/**
* Store the current lock task mode. Possible values:
@@ -298,6 +305,11 @@ public class LockTaskController {
return false;
}
+ // Allow emergency calling when the device is protected by a locked keyguard
+ if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
+ return false;
+ }
+
return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
}
@@ -306,6 +318,37 @@ public class LockTaskController {
& DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS) != 0;
}
+ private boolean isKeyguardAllowed(int userId) {
+ return (getLockTaskFeaturesForUser(userId)
+ & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
+ }
+
+ private boolean isEmergencyCallTask(TaskRecord task) {
+ final Intent intent = task.intent;
+ if (intent == null) {
+ return false;
+ }
+
+ // 1. The emergency keypad activity launched on top of the keyguard
+ if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
+ return true;
+ }
+
+ // 2. The intent sent by the keypad, which is handled by Telephony
+ if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
+ return true;
+ }
+
+ // 3. Telephony then starts the default package for making the call
+ final TelecomManager tm = getTelecomManager();
+ final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
+ if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Stop the current lock task mode.
*
@@ -686,11 +729,10 @@ public class LockTaskController {
mWindowManager.reenableKeyguard(mToken);
} else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
- int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
- if ((DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD & lockTaskFeatures) == 0) {
- mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
- } else {
+ if (isKeyguardAllowed(userId)) {
mWindowManager.reenableKeyguard(mToken);
+ } else {
+ mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
}
} else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
@@ -784,6 +826,15 @@ public class LockTaskController {
return mLockPatternUtils;
}
+ @Nullable
+ private TelecomManager getTelecomManager() {
+ if (mTelecomManager == null) {
+ // We don't preserve the TelecomManager object to save memory
+ return mContext.getSystemService(TelecomManager.class);
+ }
+ return mTelecomManager;
+ }
+
// Should only be called on the handler thread
@NonNull
private LockTaskNotify getLockTaskNotify() {
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
index 54df744ad41b..d2ae22b43445 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
@@ -30,6 +30,7 @@ import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
import static android.os.Process.SYSTEM_UID;
+import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_LOCKED;
import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_PINNED;
@@ -53,6 +54,7 @@ import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import android.telecom.TelecomManager;
import android.util.Pair;
import com.android.internal.statusbar.IStatusBarService;
@@ -90,6 +92,7 @@ public class LockTaskControllerTest {
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private LockTaskNotify mLockTaskNotify;
@Mock private StatusBarManagerInternal mStatusBarManagerInternal;
+ @Mock private TelecomManager mTelecomManager;
@Mock private RecentTasks mRecentTasks;
private LockTaskController mLockTaskController;
@@ -118,6 +121,7 @@ public class LockTaskControllerTest {
mLockTaskController.setWindowManager(mWindowManager);
mLockTaskController.mStatusBarService = mStatusBarService;
mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
+ mLockTaskController.mTelecomManager = mTelecomManager;
mLockTaskController.mLockPatternUtils = mLockPatternUtils;
mLockTaskController.mLockTaskNotify = mLockTaskNotify;
@@ -209,7 +213,7 @@ public class LockTaskControllerTest {
@Test
public void testLockTaskViolation() throws Exception {
- // GIVEN one task records with whitelisted auth that is in lock task mode
+ // GIVEN one task record with whitelisted auth that is in lock task mode
TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
@@ -234,6 +238,38 @@ public class LockTaskControllerTest {
}
@Test
+ public void testLockTaskViolation_emergencyCall() throws Exception {
+ // GIVEN one task record with whitelisted auth that is in lock task mode
+ TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
+ mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
+
+ // GIVEN tasks necessary for emergency calling
+ TaskRecord keypad = getTaskRecord(new Intent().setComponent(EMERGENCY_DIALER_COMPONENT),
+ TaskRecord.LOCK_TASK_AUTH_PINNABLE);
+ TaskRecord callAction = getTaskRecord(new Intent(Intent.ACTION_CALL_EMERGENCY),
+ TaskRecord.LOCK_TASK_AUTH_PINNABLE);
+ TaskRecord dialer = getTaskRecord("com.example.dialer", TaskRecord.LOCK_TASK_AUTH_PINNABLE);
+ when(mTelecomManager.getSystemDialerPackage())
+ .thenReturn(dialer.intent.getComponent().getPackageName());
+
+ // GIVEN keyguard is allowed for lock task mode
+ mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_KEYGUARD);
+
+ // THEN the above tasks should all be allowed
+ assertFalse(mLockTaskController.isLockTaskModeViolation(keypad));
+ assertFalse(mLockTaskController.isLockTaskModeViolation(callAction));
+ assertFalse(mLockTaskController.isLockTaskModeViolation(dialer));
+
+ // GIVEN keyguard is disallowed for lock task mode (default)
+ mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NONE);
+
+ // THEN the above tasks should all be blocked
+ assertTrue(mLockTaskController.isLockTaskModeViolation(keypad));
+ assertTrue(mLockTaskController.isLockTaskModeViolation(callAction));
+ assertTrue(mLockTaskController.isLockTaskModeViolation(dialer));
+ }
+
+ @Test
public void testStopLockTaskMode() throws Exception {
// GIVEN one task record with whitelisted auth that is in lock task mode
TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
@@ -568,10 +604,15 @@ public class LockTaskControllerTest {
}
private TaskRecord getTaskRecord(String pkg, int lockTaskAuth) {
+ final Intent intent = new Intent()
+ .setComponent(ComponentName.createRelative(pkg, TEST_CLASS_NAME));
+ return getTaskRecord(intent, lockTaskAuth);
+ }
+
+ private TaskRecord getTaskRecord(Intent intent, int lockTaskAuth) {
TaskRecord tr = mock(TaskRecord.class);
tr.mLockTaskAuth = lockTaskAuth;
- tr.intent = new Intent()
- .setComponent(ComponentName.createRelative(pkg, TEST_CLASS_NAME));
+ tr.intent = intent;
tr.userId = TEST_USER_ID;
return tr;
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 92d458f13cd1..6dcc3da15882 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -582,13 +582,21 @@ public class TelecomManager {
"android.telecom.extra.CALL_BACK_INTENT";
/**
+ * The dialer activity responsible for placing emergency calls from, for example, a locked
+ * keyguard.
+ * @hide
+ */
+ public static final ComponentName EMERGENCY_DIALER_COMPONENT =
+ ComponentName.createRelative("com.android.phone", ".EmergencyDialer");
+
+ /**
* The following 4 constants define how properties such as phone numbers and names are
* displayed to the user.
*/
/**
* Indicates that the address or number of a call is allowed to be displayed for caller ID.
- */
+ */
public static final int PRESENTATION_ALLOWED = 1;
/**