Enable outgoing emergency calls in LockTask mode.
As part of the LockTask 2.0 work, we allow DPCs to enable the system lock
screen in LockTask mode. When the device is protected by a PIN, pattern, or
password, the lock screen will have an entry point to the emergency dialer
which allows the user to make emergency calls (e.g., 911).
Therefore, we whitelist the activities that are necessary to place this
outgoing emergency call when LOCK_TASK_FEATURE_KEYGUARD is enabled.
Bug: 68750910
Test: bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest
Test: CTS verifier > CTS verifier > Managed provisioning > Device owner tests
> LockTask UI
Change-Id: Iaeeec2c462b978d2d201c5660024a3dd7283ae07
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -233,6 +237,38 @@ public class LockTaskControllerTest {
|
||||
TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV)));
|
||||
}
|
||||
|
||||
@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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -581,6 +581,14 @@ public class TelecomManager {
|
||||
public static final String EXTRA_CALL_BACK_INTENT =
|
||||
"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.
|
||||
@@ -588,7 +596,7 @@ public class TelecomManager {
|
||||
|
||||
/**
|
||||
* Indicates that the address or number of a call is allowed to be displayed for caller ID.
|
||||
*/
|
||||
*/
|
||||
public static final int PRESENTATION_ALLOWED = 1;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user