Diagramas detallados del reacondicionado de móviles
Desarrolla el diagrama de alto nivel estado a estado, encajando cada caja del Lucidchart "Diagrama reparació Vincle Digital" en el estado de DeviceHub donde ocurre.
Leyenda
Todos los diagramas usan los mismos colores:
| Color | Significado |
|---|---|
| Azul | Algo queda escrito en DeviceHub: evidencia, cambio de estado, nota o propiedad |
| Amarillo | Checkpoint: evidencia de DH-scan o snapshot de workbench-android |
| Rojo | Salida a DISMANTLE. Siempre con nota del motivo |
| Verde | Sale del estado hacia el siguiente del camino normal |
| Morado | Estado nuevo que no existe todavía en DeviceHub |
| Gris | Documento o ficha de apoyo (cajas "documento" del Lucidchart) |
1. Máquina de estados
La vista completa: qué estados existen y qué transiciones son válidas. El detalle de cada estado viene en las secciones siguientes.
stateDiagram-v2
direction TB
state "INBOX" as INBOX
state "VISUAL INSPECTION" as VI
state "PENDING DONOR (nuevo)" as PD
state "INSTALL" as INSTALL
state "TEST" as TEST
state "REPAIR" as REPAIR
state "PACKAGING" as PACK
state "DONATION" as DON
state "IN USE (nuevo)" as USE
state "DISMANTLE" as DIS
[*] --> INBOX: móvil recibido,<br/>primer POST de DH-scan
INBOX --> VI: registrado
INBOX --> DIS: daño evidente
VI --> INSTALL: arranca y es accesible
VI --> PD: bloqueado con PIN<br/>o FRP
VI --> DIS: no carga<br/>o no arranca
PD --> INSTALL: se recupera el acceso<br/>o se libera la gestión
PD --> DIS: sin respuesta en 30 días
INSTALL --> TEST: reset hecho,<br/>usuario de test configurado
INSTALL --> DIS: obsoleto
INSTALL --> PD: pide una contraseña<br/>o liberar la gestión
TEST --> PACK: apto según<br/>criterios de entrega
TEST --> REPAIR: requiere<br/>reparación
REPAIR --> TEST: reparación<br/>completada
REPAIR --> DIS: no reparable<br/>o reparación no viable
PACK --> DON: entregado a receptor
PACK --> REPAIR: no arranca<br/>tras el reset II
PACK --> PD: pide la cuenta<br/>anterior (FRP)
DON --> USE: receptor lo usa
USE --> VI: devolución o<br/>cambio de persona
USE --> DIS: se rompe sin arreglo
DIS --> [*]
El procedimiento interno de REPAIR queda fuera del alcance de este documento. Una reparación completada requiere repetir TEST antes de decidir si el dispositivo es apto para PACKAGING.
2. INBOX · Etiquetado y cribado rápido
Es un cribado de pocos segundos por móvil: se etiqueta, se da de alta y se aparta lo que se ve a simple vista que no sirve. No se enciende el móvil ni se busca información del modelo: en este punto se hace un primer registro en DeviceHub para tener constancia de los móviles que recibimos.
flowchart TD
START(["Móvil recibido"]) --> PEGAR["Pegar la siguiente etiqueta<br/>preimpresa de la plancha"]
PEGAR --> SCAN["DH-scan o WebForm de DeviceHub:<br/>custom_id, fotos y tipo"]:::checkpoint
SCAN --> LBL{"¿Tiene etiqueta<br/>del fabricante a la vista?"}
LBL -->|"Sí"| OCR["DH-scan: barcode u OCR<br/>fabricante, modelo, serial,<br/>product code, GTIN"]:::checkpoint
LBL -->|"No"| POST
OCR --> POST["Primer POST de evidencia<br/>a DeviceHub: el móvil<br/>consta como recibido"]:::dh
POST --> ST_INBOX["Estado INBOX"]:::dh
ST_INBOX --> CRIBA{"Cribado a simple vista"}
CRIBA -->|"iPhone"| IPH(["Fuera del flujo Android<br/>ver preguntas abiertas"]):::reject
CRIBA -->|"Móvil de teclas<br/>u otro aparato"| OTRO(["Reclasificar o<br/>DISMANTLE"]):::reject
CRIBA -->|"Batería hinchada"| N_BAT["Nota: [BATERIA-HINCHADA]<br/>+ foto"]:::dh
N_BAT --> DIS(["DISMANTLE"]):::reject
CRIBA -->|"Partido, mojado<br/>u otro daño grave"| N_DEST["Nota: [DAÑO-EVIDENTE]<br/>+ foto"]:::dh
N_DEST --> DIS
CRIBA -->|"Móvil o tablet Android"| NEXT(["→ VISUAL INSPECTION"]):::ok
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef checkpoint fill:#fff3cd,stroke:#997404,color:#664d03
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
ID y etiqueta. Las etiquetas se imprimen por adelantado en planchas A4
con numeración correlativa, con la herramienta generar_planchas.py.
- El QR lleva solo el número, no una URL: DH-scan guarda el texto del QR tal
cual como
custom_id. En workbench-android el número se teclea y la app comprueba en DeviceHub que existe.
Solo lo evidente. Aquí se descarta lo que no necesita comprobación: pantalla partida en trozos, batería hinchada (apartar el aparato por riesgo de incendio) o señales claras de agua. El resto del hardware lo prueba workbench-android en TEST.
Queda en DeviceHub al salir de INBOX:
| Dato | Origen |
|---|---|
custom_id |
QR de la etiqueta, leído por DH-scan y enviado en el primer POST |
| tipo | DeviceType de móvil o de tablet de la institución |
| fotos | DH-scan o WebForm de DeviceHub |
| fabricante, modelo, serial, product code, GTIN | Barcode u OCR de la etiqueta, si la hay, como propiedades |
estado INBOX |
La guía lo marca tras el primer POST, con el token API o a mano |
3. VISUAL INSPECTION · Carga, arranque y bloqueo
Responde a lo que workbench-android no puede comprobar porque aún no está instalado: si el móvil carga, si arranca y si podemos entrar. Todo lo demás se mira en otro sitio:
flowchart TD
IN(["Desde INBOX<br/>o desde IN USE"]) --> ST_VI["Estado VISUAL INSPECTION"]:::dh
ST_VI --> CARGA{"Enchufar 15 min<br/>¿carga? icono o LED"}
CARGA -->|"No"| OTRO_CAB["Probar otro cable<br/>y limpiar conector"]
OTRO_CAB --> CARGA2{"¿Carga ahora?"}
CARGA2 -->|"No"| N_NOCAR["Nota: no carga"]:::dh
N_NOCAR --> DIS1(["DISMANTLE"]):::reject
CARGA2 -->|"Sí"| ARRANCA
CARGA -->|"Sí"| ARRANCA{"¿Arranca?"}
ARRANCA -->|"No"| N_NOARR["Nota: no arranca<br/>bootloop o pantalla negra"]:::dh
N_NOARR --> DIS2(["DISMANTLE"]):::reject
ARRANCA -->|"Sí"| PANT{"¿Qué pantalla sale?"}
PANT -->|"Escritorio sin bloqueo"| OK(["→ INSTALL"]):::ok
PANT -->|"Asistente inicial"| FRP{"¿Pide la cuenta<br/>anterior? FRP"}
FRP -->|"No"| OK
FRP -->|"Sí"| PEND
PANT -->|"Pantalla de bloqueo"| PIN{"¿El PIN venía<br/>con la donación<br/>y funciona?"}
PIN -->|"Sí"| OK
PIN -->|"No"| PEND(["→ PENDING DONOR"]):::newstate
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
classDef newstate fill:#e2d9f3,stroke:#59359a,color:#2f1c6a
La carga va antes que el arranque porque un móvil sin batería no arranca y no se puede distinguir de uno roto. No hace falta cargarlo más: basta con que encienda. Si hay un tester USB a mano, se puede usar para comprobar si el móvil está consumiendo corriente aunque no muestre ningún icono o LED. El consumo concreto depende del modelo, de la batería y de la fase de carga.
Nunca se prueban PINs a ciegas: tras varios intentos el móvil se bloquea por tiempo o se borra, y lo segundo deja el FRP armado.
4. PENDING DONOR (RELEASE) · Espera de liberación (estado nuevo)
Espera la actuación del donante, propietario o empresa para obtener un PIN, completar la verificación FRP o retirar la gestión empresarial.
flowchart TD
IN(["Desde VISUAL INSPECTION,<br/>INSTALL o PACKAGING"]) --> ST_PD["Estado PENDING DONOR<br/>nota: fecha límite = hoy + 30 días"]:::dh
ST_PD --> GUARDAR["Guardar en estantería<br/>de espera, etiquetado"]
GUARDAR --> CONTACTO{"¿Hay contacto del donante,<br/>propietario o empresa?"}
CONTACTO -->|"No"| N_ANON["Nota: donante anónimo"]:::dh
N_ANON --> DIS1(["DISMANTLE"]):::reject
CONTACTO -->|"Sí"| MSG["Pedir que desbloquee el dispositivo,<br/>complete la verificación FRP<br/>o retire la gestión empresarial"]:::dh
MSG --> R1{"¿Responde<br/>en 7 días?"}
R1 -->|"No"| REC["Recordatorio"]:::dh
REC --> R2{"¿Responde antes<br/>de la fecha límite?"}
R2 -->|"No"| N_TIME["Nota: sin respuesta<br/>en 30 días"]:::dh
N_TIME --> DIS2(["DISMANTLE"]):::reject
R1 -->|"Sí"| QUE
R2 -->|"Sí"| QUE{"¿Qué responde?"}
QUE -->|"Da el PIN"| PIN["Probar PIN para desbloquear el móvil"]
QUE -->|"FRP activo"| FRP_OK["El donante completa<br/>la verificación con una cuenta<br/>previamente sincronizada"]
QUE -->|"Gestión empresarial"| MDM_OK["La empresa retira<br/>MDM, zero-touch o Knox"]
QUE -->|"No quiere o no puede"| N_NEG["Nota: donante rechaza"]:::dh
N_NEG --> DIS3(["DISMANTLE"]):::reject
PIN --> FUNC{"¿Desbloquea?"}
FUNC -->|"No"| MSG
FUNC -->|"Sí"| N_OK["Nota: acceso recuperado"]:::dh
FRP_OK --> N_OK
MDM_OK --> N_OK
N_OK --> OK(["→ INSTALL"]):::ok
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
5. INSTALL · Borrado de cuentas, reset y registro con workbench-android
flowchart TD
IN(["Desde VISUAL INSPECTION<br/>o PENDING DONOR"]) --> ST_IN["Estado INSTALL"]:::dh
ST_IN --> EMM{"¿Gestión empresarial?<br/>perfil de trabajo,<br/>zero-touch, Knox"}
EMM -->|"Sí"| N_EMM["Nota: bloqueo MDM empresarial<br/>pedir baja a la empresa"]:::dh
N_EMM --> PEND_MDM(["→ PENDING DONOR"]):::newstate
EMM -->|"No"| BANDEJA["Sacar bandeja: retirar<br/>SIM y SD del donante"]
BANDEJA --> DONATE["Instalar donate-android<br/>APK sin permisos ni red"]
DONATE --> CUENTAS["donate-android guía:<br/>eliminar todas las cuentas,<br/>Google y fabricante"]
CUENTAS --> PASS{"¿Pide una contraseña<br/>que no tenemos?"}
PASS -->|"Sí"| PEND(["→ PENDING DONOR"]):::newstate
PASS -->|"No"| LOCK["Quitar bloqueo de pantalla"]
LOCK --> RESET["donate-android abre el<br/>factory reset del sistema"]
RESET --> ASIST["Arranca en<br/>asistente inicial"]
ASIST --> USR["Configurar usuario de test<br/>sin cuenta Google<br/>idioma, fecha, sin PIN"]
USR --> WIFI_CFG["Conectar a WiFi del taller"]
WIFI_CFG --> INSTWB["Instalar workbench-android<br/>APK"]
INSTWB --> WBID["workbench-android:<br/>teclear el número de la etiqueta<br/>y comprobarlo en DeviceHub"]
WBID --> INV["Snapshot de inventario<br/>modelo, Android, parche,<br/>RAM, almacenamiento, batería"]:::checkpoint
INV --> OBS{"¿Obsoleto?<br/>parche de hace<br/>más de X años"}
OBS -->|"Sí"| N_OBS["Nota: obsoleto<br/>modelo, Android y parche"]:::dh
N_OBS --> DIS0(["DISMANTLE"]):::reject
OBS -->|"No"| OK(["→ TEST"]):::ok
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef checkpoint fill:#fff3cd,stroke:#997404,color:#664d03
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
classDef newstate fill:#e2d9f3,stroke:#59359a,color:#2f1c6a
donate-android guía el borrado de cuentas y abre el factory reset del
propio Android: la app no puede hacer el reset ni saltarse nada. No pide
permisos ni tiene acceso a red, así que se puede instalar en un móvil que aún
tiene datos del donante. workbench-android, en cambio, se instala después del
reset. La última APK publicada se descarga desde
apps.sergiogimenez.com/workbench.
El orden importa: cuentas fuera antes del reset. Si se resetea con la cuenta puesta, el FRP aparece y solo el propietario puede quitarlo. No se intenta ningún bypass de FRP.
Qué reporta workbench-android
Lo que necesitamos del registro y lo que envía la app en el snapshot. Lo que llega a DeviceHub como propiedad se ve en la ficha del producto.
| Dato | Para qué | En la app | En DeviceHub |
|---|---|---|---|
custom_id |
Unir con el alta de DH-scan | Se teclea y se comprueba que existe en DeviceHub antes de enviar (la etiqueta está en la trasera del propio móvil, su cámara no la ve) | Identificador del producto |
| Tipo | Móvil o tablet | Smartphone o Tablet (pantalla ≥ 600 dp) |
Tipo del producto |
| Fabricante, marca, modelo | Ficha | Sí, de Build |
Sí |
| Versión de Android, API | Ficha, obsoleto | Sí | android:version, android:api_level |
| Parche de seguridad | Decidir obsoleto | Sí, Build.VERSION.SECURITY_PATCH |
android:security_patch |
| Obsoleto | Salida a DISMANTLE | No | Falta la regla: se decide con android:security_patch |
| CPU, RAM, almacenamiento, pantalla, cámaras, sensores | Ficha | Sí | Componentes |
| Batería: nivel, salud, voltaje, temperatura | Ficha, TEST | Sí | Componente batería |
| Ciclos de batería | Desgaste | Solo API 34+ y según fabricante | Sin alternativa fiable |
| Salud de batería en % | Desgaste | No, fijo a null |
Depende del fabricante |
| Serial | Ficha | No | No accesible sin privilegios desde API 29. Sale de la etiqueta (DH-scan) |
| IMEI | Ficha, trazabilidad | No | No accesible desde API 29. *#06# a mano |
| SIM o SD dentro | Control de INSTALL, antes del reset | Parcial: el test de SIM pide retirarla | La SD no se comprueba |
| Specs PD (carga rápida) | Cargador de entrega | No | No lo expone Android: ficha del fabricante |
Falta fijar la X del criterio de obsoleto.
6. TEST · Diagnóstico con workbench-android
La idea es que todos los tests se hagan desde workbench-android, sin pruebas a mano ni diagnósticos de fábrica: es la única forma de que el taller no pierda tiempo y de que cada resultado quede en el snapshot.
flowchart TD
IN(["Desde INSTALL"]) --> ST_T["Estado TEST"]:::dh
ST_T --> WB["Completar todos los tests<br/>en Workbench Android<br/>y enviar el snapshot"]:::checkpoint
WB --> PROPS["Resultados hwtest:*<br/>guardados en Propiedades<br/>de DeviceHub"]:::dh
PROPS --> DEC{"¿Cumple los criterios<br/>de entrega?"}
DEC -->|"Sí"| PACK(["→ PACKAGING"]):::ok
DEC -->|"No"| REP(["→ REPAIR"]):::ok
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef checkpoint fill:#fff3cd,stroke:#997404,color:#664d03
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
Workbench guía todas las pruebas —incluidas SIM y batería cuando corresponda—,
registra PASS, FAIL o SKIP y envía el snapshot. La guía del taller solo
confirma que se ha completado ese recorrido, sin duplicarlo como checklist.
Los resultados quedan en DeviceHub y, según los criterios de entrega, el móvil
pasa a PACKAGING o REPAIR.
Qué hace workbench-android
Todos los tests del diagrama están en la app. Cada resultado llega a DeviceHub
como propiedad hwtest:<id>. Si cambia entre
pasadas, el cambio queda en el log del producto.
| Test | Ids de resultado | Cómo decide |
|---|---|---|
| Pantalla, táctil, multitáctil | screen, touch, multitouch |
Operario; táctil pasa solo al cubrir la rejilla |
| Sensores | accelerometer, gyroscope, magnetometer, proximity, light |
Pasa si la lectura cambia; SKIP si no existe |
| Vibración, linterna | vibration, flashlight |
Operario |
| Carga | charging |
Pass solo con el cargador detectado |
| WiFi | wifi |
Pass solo con WiFi validada por el sistema |
| Audio | speaker, earpiece, microphone |
Operario; auricular SKIP si no hay; el micrófono graba y reproduce |
| Cámaras | camera_back, camera_front |
Operario con la vista previa; SKIP si no hay |
| Botones | volume_up, volume_down, power |
Detectados: teclas de volumen y pantalla apagada |
| Bluetooth | bluetooth |
Pass con al menos un dispositivo visible encontrado |
| GPS | gps |
Pass con satélites visibles; la nota lleva satélites y fix |
| SIM | sim, cellular_network, call, mobile_data |
SIM lista, registro en red, llamada por el marcador, datos validados. SKIP sin telefonía |
| Batería | battery_drain |
Descarga de 15, 30 o 60 min; la caída va en la nota |
Sin probar todavía en un móvil real: leer un QR real, auricular, micrófono con voz, Bluetooth con dispositivos cerca y la llamada. En el emulador funcionan el recorrido completo, la reanudación y el envío a DeviceHub.
7. PACKAGING → DONATION → IN USE · Preparación, entrega y uso
flowchart TD
IN(["Desde TEST<br/>apto para entrega"]) --> ST_P["Estado PACKAGING"]:::dh
ST_P --> RESET2["Reset II<br/>factory reset desde Ajustes:<br/>borra usuario de test y WiFi"]
RESET2 --> ASIST{"¿Arranque correcto en asistente<br/>inicial sin pedir cuenta?"}
ASIST -->|"No"| REP(["→ REPAIR"]):::ok
ASIST -->|"Sí"| FRP{"¿Pide una cuenta<br/>anterior? FRP"}
FRP -->|"Sí"| PEND(["→ PENDING DONOR"]):::newstate
FRP -->|"No"| APAGAR["Apagar con<br/>batería al 50-80 %"]
APAGAR --> LIMPIEZA["Limpieza exterior<br/>y protector si procede"]
LIMPIEZA --> KIT["Kit: móvil, cargador,<br/>cable, funda,<br/>guía de primeros pasos"]
KIT --> ETIQ["Etiqueta QR visible<br/>con custom_id"]
ETIQ --> ESPERA["Estantería de listos"]
ESPERA --> ASIGN{"¿Hay receptor<br/>asignado?"}
ASIGN -->|"No"| ESPERA
ASIGN -->|"Sí"| ENTREGA["Entrega al receptor<br/>firma de recepción"]
ENTREGA --> ST_D["Estado DONATION<br/>nota: entidad o receptor"]:::dh
ST_D --> CONF["Primera configuración<br/>con el receptor si lo necesita"]
CONF --> ST_U["Estado IN USE"]:::newstate
ST_U --> CHK["Pasada de workbench-android<br/>periódica o al volver"]:::checkpoint
CHK --> EVENTO{"¿Qué pasa?"}
EVENTO -->|"Sigue en uso"| ST_U
EVENTO -->|"Cambio de persona<br/>o devolución"| VI(["→ VISUAL INSPECTION"]):::ok
EVENTO -->|"Se rompe"| REV{"¿Reparable?"}
REV -->|"Sí"| VI
REV -->|"No"| DIS(["DISMANTLE"]):::reject
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
classDef ok fill:#d1e7dd,stroke:#146c43,color:#0a3622
classDef checkpoint fill:#fff3cd,stroke:#997404,color:#664d03
classDef dh fill:#cfe2ff,stroke:#0a58ca,color:#052c65
classDef newstate fill:#e2d9f3,stroke:#59359a,color:#2f1c6a
La vuelta desde IN USE entra por VISUAL INSPECTION y no por TEST: el móvil ha estado en manos de otra persona y puede volver con cuentas, PIN o daños nuevos.
Cada fila DONATION del historial abre un periodo de uso y la siguiente
transición lo cierra. Con eso se calculan las horas de impacto social sin
marcar evidencias a mano.
8. DISMANTLE · Catálogo de motivos
Todas las salidas rojas acaban aquí. Para poder contar después por qué se
pierden móviles, el motivo tiene que ser uno de esta lista y ir al principio de
la nota del cambio de estado, por ejemplo [NO-CARGA] probado con dos cables.
flowchart LR
subgraph INBOX
M2["NO-ANDROID"]
M0["DAÑO-EVIDENTE"]
M4["BATERIA-HINCHADA"]
end
subgraph VISUAL_INSPECTION["VISUAL INSPECTION"]
M5["NO-CARGA"]
M6["NO-ARRANCA"]
end
subgraph PENDING_DONOR["PENDING DONOR"]
M7["DONANTE-ANONIMO"]
M8["SIN-RESPUESTA"]
M9["DONANTE-RECHAZA"]
end
subgraph INSTALL
M1["OBSOLETO"]
M10["MDM-EMPRESA"]
end
subgraph IN_USE["IN USE"]
M19["ROTO-EN-USO"]
end
INBOX --> DIS
VISUAL_INSPECTION --> DIS
PENDING_DONOR --> DIS
INSTALL --> DIS
IN_USE --> DIS
DIS["DISMANTLE"]:::reject --> DEST{"Destino"}
DEST --> PIEZAS["Donante de piezas<br/>pantalla, batería, cámara"]
DEST --> WEEE["Gestor autorizado WEEE<br/>con borrado certificado<br/>si no se pudo resetear"]
classDef reject fill:#f8d7da,stroke:#b02a37,color:#58151c
Preguntas abiertas
Decisiones que tomé para poder dibujar y que conviene validar:
- iPhone. Que hacemos con ellos?
- Criterio de obsoleto. ¿Cuántos años de antigüedad del parche de seguridad hacen obsoleto un móvil?
- Umbral de batería. "Descarga excesiva en 60 minutos" necesita un número concreto por grado.