English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Android6Detalles de la función de fijación de pantalla .0

Quizás algunos de ustedes no saben qué es esto, primero me explicaré, android6.0 en la configuración-Seguridad-Después de activar la pantalla fija, luego mantener presionado el botón de inicio para aparecer varios Activity recientes y seleccionar un botón de alfiler para activar la función de pantalla fija.

Después de activar la pantalla fija, la pantalla solo puede cambiar entre las Activity en el Task configurado.

1. Establecer pantalla fija

Vamos a ver primero SystemUI/src/com/android/systemui/recents/El código de ScreenPinningRequest.java, este código es el que se muestra al mantener presionado el botón de inicio y aparecer varios Activity, luego al presionar el botón de alfiler de la imagen. Aquí se llama directamente a la función startLockTaskModeOnCurrent de AMS.

@Override 
public void onClick(View v) { 
if (v.getId() == R.id.screen_pinning_ok_button || mRequestWindow == v) { 
try { 
ActivityManagerNative.getDefault().startLockTaskModeOnCurrent(); 
} catch (RemoteException e) {} 
} 
clearPrompt(); 
}

Vamos a ver la función startLockTaskModeOnCurrent de AMS, primero llama a topRunningActivityLocked de ActivityStackSupervisor para obtener el Activity más reciente, luego llama a la función startLockTaskModeLocked, el parámetro es TaskRecord.

public void startLockTaskModeOnCurrent() throws RemoteException { 
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, 
"startLockTaskModeOnCurrent"); 
long ident = Binder.clearCallingIdentity(); 
try { 
sincronizado (this) { 
ActivityRecord r = mStackSupervisor.topRunningActivityLocked(); 
if (r != null) { 
startLockTaskModeLocked(r.task); 
} 
} 
} 
Binder.restoreCallingIdentity(ident); 
} 
}

Vamos a ver la función topRunningActivityLocked, primero obtenemos el Activity más reciente de mFocusedStack. Si no lo encuentra,然后再遍历所有的mStacks获取。

ActivityRecord topRunningActivityLocked() { 
final ActivityStack focusedStack = mFocusedStack; 
ActivityRecord r = focusedStack.topRunningActivityLocked(null); 
if (r != null) { 
return r; 
} 
// Regresar a la pila de inicio. 
final ArrayList<ActivityStack> stacks = mHomeStack.mStacks; 
for (int stackNdx = stacks.size()} - 1; stackNdx >= 0; --stackNdx) { 
final ActivityStack stack = stacks.get(stackNdx); 
if (stack != focusedStack && isFrontStack(stack)) { 
r = stack.topRunningActivityLocked(null); 
if (r != null) { 
return r; 
} 
} 
} 
return null; 
}

En la función startLockTaskModeLocked, se llama principalmente a la función setLockTaskModeLocked de ActivityStackSupervisor, ahora veamos esta función, nuestro task no es null, la primera vez que mLockTaskModeTasks está vacío, se envía un mensaje LOCK_TASK_START_MSG

void establecerLockTaskModeBloqueado(TaskRecord task, int lockTaskModeState, String reason, 
boolean andResume) { 
if (task == null) { 
// Salir del modo de tarea bloqueada si es necesario 
final TaskRecord lockedTask = obtenerTareaBloqueadaBloqueada(); 
if (lockedTask != null) { 
eliminarTareaBloqueadaBloqueada(lockedTask); 
if (!mLockTaskModeTasks.isEmpty()) { 
// Hay tareas bloqueadas restantes, solo se puede completar esta tarea, no se puede desbloquear. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"establecerLockTaskModeBloqueado: Tareas restantes, no se puede desbloquear"); 
lockedTask.performClearTaskLocked(); 
resumirActivitiesSuperioresBloqueadas(); 
return; 
} 
} 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: No hay tareas para desbloquear. Llamadores=" + Debug.getCallers(4)); 
return; 
} 
// Should have already been checked, but do it again. 
if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: Can't lock due to auth") 
return; 
} 
if (isLockTaskModeViolation(task)) { 
Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); 
return; 
} 
if (mLockTaskModeTasks.isEmpty()) { 
// Primero locktask. 
final Message lockTaskMsg = Message.obtain(); 
lockTaskMsg.obj = task.intent.getComponent().getPackageName(); 
lockTaskMsg.arg1 = task.userId; 
lockTaskMsg.what = LOCK_TASK_START_MSG;//enviar mensaje 
lockTaskMsg.arg2 = lockTaskModeState; 
mHandler.sendMessage(lockTaskMsg); 
} 
// Añadirlo o moverlo a la parte superior. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskModeLocked: Bloqueando a " + task + 
" Llamadores=" + Debug.getCallers(4)); 
mLockTaskModeTasks.remove(task); 
mLockTaskModeTasks.add(task);//Añadirlo a mLockModeTasks 
if (task.mLockTaskUid == -1) { 
task.mLockTaskUid = task.effectiveUid; 
} 
if (andResume) { 
findTaskToMoveToFrontLocked(task, 0, null, reason);//Colocar la tarea en primer plano 
resumirActivitiesSuperioresBloqueadas();//Mostrar nueva Activity 
} 
}

Vamos a ver el procesamiento de mensajes, en el procesamiento de mensajes se llama principalmente a la función disableKeyguard de WMS.

case LOCK_TASK_START_MSG: { 
// Cuando se inicia la tarea de bloqueo, deshabilitamos las barras de estado. 
try { 
if (mLockTaskNotify == null) { 
mLockTaskNotify = new LockTaskNotify(mService.mContext); 
} 
mLockTaskNotify.show(true); 
mLockTaskModeState = msg.arg2; 
if (getStatusBarService() != null) { 
int flags = 0; 
if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { 
flags = StatusBarManager.DISABLE_MASK 
& (~StatusBarManager.DISABLE_BACK); 
} else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 
flags = StatusBarManager.DISABLE_MASK 
& (~StatusBarManager.DISABLE_BACK) 
& (~StatusBarManager.DISABLE_HOME) 
& (~StatusBarManager.DISABLE_RECENT); 
} 
getStatusBarService().disable(flags, mToken, 
mService.mContext.getPackageName()); 
} 
mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG); 
if (getDevicePolicyManager() != null) { 
getDevicePolicyManager().notifyLockTaskModeChanged(true, 
(String)msg.obj, msg.arg1); 
} 
} catch (RemoteException ex) { 
throw new RuntimeException(ex); 
} 
} break;

Segundo, el proceso de inicio de Activity después de fijar la pantalla

Después de fijar la pantalla, si iniciamos otra Activity de TaskRecord que no se puede iniciar, veamos este principio. En la función startActivityUncheckedLocked se llama a la función isLockTaskModeViolation para determinar si se debe continuar con el proceso de inicio de Activity, veamos esta función, que llama a getLockedTaskLocked para ver mLockTaskModeTasks (es decir, las Task que bloquean la pantalla), si el task actual es el mismo que el task en la pantalla fija, devolver false directamente para continuar con el proceso de inicio de Activity, y si no es así, necesitamos ver la variable mLockTaskAuth del task.

boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { 
if (getLockedTaskLocked() == task && !isNewClearTask) { 
return false; 
} 
final int lockTaskAuth = task.mLockTaskAuth; 
switch (lockTaskAuth) { 
case LOCK_TASK_AUTH_DONT_LOCK: 
return !mLockTaskModeTasks.isEmpty(); 
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: 
case LOCK_TASK_AUTH_LAUNCHABLE: 
case LOCK_TASK_AUTH_WHITELISTED: 
return false; 
case LOCK_TASK_AUTH_PINNABLE: 
// No se pueden lanzar tareas pinnables sobre tareas locktask. 
return !mLockTaskModeTasks.isEmpty(); 
default: 
Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth); 
return true; 
} 
}

Vamos a ver la función setLockedTaskAuth de TaskRecord, se llama a la función setIntent cuando se crea un nuevo TaskRecord, y la función setIntent es llamada en el constructor de TaskRecord. Vamos a ver esta función, el valor de mLockTaskAuth se determina según mLockTaskMode, y mLockTaskMode es pasado por ActivityInfo, este valor se construye cuando se analiza AndroidManifest.xml en PKMS, por defecto es LOCK_TASK_LAUNCH_MODE_DEFAULT, y cuando no hay lista blanca, el valor final de mLockTaskAuth es LOCK_TASK_AUTH_PINNABLE.

void setLockTaskAuth() { 
if (!mPrivileged && 
(mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS || 
mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) { 
// Non-priv apps are not allowed to use always or never, fall back to default 
mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT; 
} 
switch (mLockTaskMode) { 
case LOCK_TASK_LAUNCH_MODE_DEFAULT: 
mLockTaskAuth = isLockTaskWhitelistedLocked() &63; 
LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE; 
break; 
case LOCK_TASK_LAUNCH_MODE_NEVER: 
mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK; 
break; 
case LOCK_TASK_LAUNCH_MODE_ALWAYS: 
mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV; 
break; 
case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED: 
mLockTaskAuth = isLockTaskWhitelistedLocked() &63; 
LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE; 
break; 
} 
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this + 
" mLockTaskAuth=" + lockTaskAuthToString()); 
}

Veamos la función isLockTaskModeViolation como sigue, actualmente el mLockTaskAuth de task es LOCK_TASK_AUTH_PINNABLE, y actualmente se encuentra en la pantalla fija, por lo que mLockTaskModeTasks no es null, y finalmente devuelve true. Esto significa que el proceso de inicio de Activity no puede continuar, lo que indica que el inicio de Activity normal será bloqueado.

case LOCK_TASK_AUTH_PINNABLE: 
// No se pueden lanzar tareas pinnables sobre tareas locktask. 
return !mLockTaskModeTasks.isEmpty();

Tres, desactivar la pantalla fija

Por último, veamos cómo desactivar la pantalla fija, la desactivación de la pantalla se realiza en PhoneStatusBar, pero debe haber teclas virtuales, es así como lo ha establecido el diseño nativo. Finalmente, se llamó a la función stopLockTaskModeOnCurrent de AMS. Esta función principalmente llama a la función stopLockTaskMode, esta función principalmente llama a la función setLockTaskModeLocked de ActivityStackSupervisor, también se llamó a esta función cuando se activó la pantalla fija, pero al observar con atención, su primer parámetro es null.

public void stopLockTaskMode() { 
final TaskRecord lockTask = mStackSupervisor.getLockedTaskLocked(); 
if (lockTask == null) { 
// Nuestra tarea aquí está terminada. 
return; 
} 
final int callingUid = Binder.getCallingUid(); 
final int lockTaskUid = lockTask.mLockTaskUid; 
// Asegúrese de que el mismo llamador para startLockTaskMode y stopLockTaskMode. 
// Es posible que lockTaskMode se haya iniciado por el proceso del sistema porque 
// android:lockTaskMode se establece a un valor de bloqueo en el manifiesto de la aplicación en lugar de 
// la aplicación que llama a startLockTaskMode. En este caso {@link TaskRecord.mLockTaskUid} será 
// será 0, por lo que comparamos callingUid con el {@link TaskRecord.effectiveUid} en su lugar. 
if (getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED && 
callingUid != lockTaskUid 
&& (lockTaskUid != 0 
|| (lockTaskUid == 0 && callingUid != lockTask.effectiveUid))) { 
lanzar nueva ExcepciónDeSeguridad("uid no válido, se esperaba ", + lockTaskUid 
+ " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid); 
} 
long ident = Binder.clearCallingIdentity(); 
try { 
Log.d(TAG, "stopLockTaskMode"); 
// Detener la tarea de bloqueo 
sincronizado (this) { 
mStackSupervisor.setLockTaskModeBloqueado(null, ActivityManager.LOCK_TASK_MODE_NONE, 
"detenerLockTask", true); 
} 
} 
Binder.restoreCallingIdentity(ident); 
} 
}

Veamos esta función, si está vacío, ahora llama a getLockedTaskLocked para obtener el TaskRecord actual del escritorio fijo, luego llama a removeLockedTaskLocked para eliminar este TaskRecord, si aún no es null, llama a resumeTopActivitiesLocked para iniciar el siguiente Activity (generalmente también el siguiente Activity bloqueado del escritorio).

Si está vacío, regrese directamente. Pero cuando iniciamos un Activity normal la próxima vez, vuelve a la normalidad, porque mLockTaskModeTasks ya está vacío.

void establecerLockTaskModeBloqueado(TaskRecord task, int lockTaskModeState, String reason, 
boolean andResume) { 
if (task == null) { 
// Salir del modo de tarea bloqueada si es necesario 
final TaskRecord lockedTask = obtenerTareaBloqueadaBloqueada(); 
if (lockedTask != null) { 
eliminarTareaBloqueadaBloqueada(lockedTask); 
if (!mLockTaskModeTasks.isEmpty()) { 
// Hay tareas bloqueadas restantes, solo se puede completar esta tarea, no se puede desbloquear. 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"establecerLockTaskModeBloqueado: Tareas restantes, no se puede desbloquear"); 
lockedTask.performClearTaskLocked(); 
resumirActivitiesSuperioresBloqueadas(); 
return; 
} 
} 
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 
"setLockTaskModeLocked: No hay tareas para desbloquear. Llamadores=" + Debug.getCallers(4)); 
return; 
}

Cuatro, ¿cómo cancelar la fijación de la pantalla sin teclas virtuales?

Como se mencionó anteriormente, sin teclas virtuales no se puede cancelar la fijación de la pantalla, mencionaremos algunas formas

1.Se puede llamar a la función stopLockTaskMode de am mediante el comando am task lock stop

2.Otra manera es modificar el código en Activity.java, llamar al método stopLockTaskMode de AMS al presionar el botón de retorno durante mucho tiempo, a continuación se muestra la implementación, Activity proporciona stopLockTask que llama al método stopLockTaskMode de AMS

public boolean onKeyLongPress(int keyCode, KeyEvent event) { 
if (keyCode == KeyEvent.KEYCODE_BACK) { 
stopLockTask(); 
} 
return false; 
}

Lo que se mencionó anteriormente es lo que el editor les ha presentado sobre Android6Detalles de la función de fijación de pantalla 0, espero que sea útil para todos. Si tienen alguna pregunta, déjenme un mensaje y editaré a tiempo. También les agradezco mucho el apoyo a la página web de Tutorial de Gritar!

Declaración: el contenido de este artículo se ha obtenido de la red, es propiedad del autor original, el contenido se ha contribuido y subido por los usuarios de Internet de manera autónoma. Este sitio no posee los derechos de propiedad, no ha sido editado por humanos y no asume la responsabilidad de las responsabilidades legales relacionadas. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, por favor reemplace # con @) para denunciar, y proporcione la evidencia relevante. Una vez verificada, este sitio eliminará inmediatamente el contenido sospechoso de infracción.

Te gustará