Qualche settimana fa ho scritto che un telefono in tasca dorme, e non c'è nessuno che possa svegliarlo. BeeBEEP non ha un server, e quindi nessuno può dare un colpetto sulla spalla a un telefono addormentato quando arriva un messaggio. Avevo raccontato cosa volevo fare, e filava tutto. Sulla carta.
La versione Android era nata e cresciuta sull'emulatore, e l'emulatore ha un difetto gentile: non dorme mai davvero. Ti dice la verità, ma non tutta. Così ho preso un telefono vero, un Samsung Galaxy A56, l'ho appoggiato su un tavolo, ho spento lo schermo e l'ho lasciato in pace. Questo è quello che mi ha raccontato.
La prima mezz'ora, dritta nel cestino
Il piano era semplice. Un computer lì accanto manda al telefono un messaggio ogni cinque minuti e si annota quando arriva. I conti li tiene Android stesso: quanta batteria spende BeeBEEP per il processore, per il Wi-Fi, per il Bluetooth, e per tenere sveglio il telefono.
Dopo trenta minuti ho guardato i numeri. Il telefono non aveva passato nemmeno un minuto in sonno profondo. Neanche uno. Era attaccato al cavo USB, e col cavo l'A56 non dorme mai davvero, qualunque cosa dica il software. Avevo misurato un telefono che faceva finta.
Da lì in poi, niente cavo. La connessione di debug passava dal Wi-Fi e restava chiusa per tutta la prova, perché nemmeno le mie misure tenessero sveglio il telefono. Mezz'ora, un'ora, e il telefono lì sul tavolo, senza che nessuno lo toccasse.
Vivo, ma sordo
La prima domanda era quella a cui l'articolo precedente aveva già risposto sulla carta: il servizio in primo piano, la notifica fissa che dice che BeeBEEP è in esecuzione. Serve davvero? E quanto costa?
Con il servizio attivo, collegato a due computer, per un'ora, due volte: 24 messaggi su 24, ognuno consegnato in meno di un secondo. Il prezzo: 0,3 mAh all'ora. Sette o otto mAh al giorno, lo 0,15% della batteria. Nella stessa ora il processore del telefono aveva consumato in tutto circa 6 mAh, e la parte di BeeBEEP era l'1,4%.
Poi ho spento il servizio. BeeBEEP è rimasto vivo, in memoria, e Android, senza dire niente, gli ha tolto la rete. Sei messaggi spediti, nessuno arrivato, per tutta la mezz'ora. Vivo, ma sordo.
Il servizio resta, attivo di default. Puoi spegnerlo, e BeeBEEP ti dice quanto ti costa.
Una frase prima di quella di Android
C'è un altro modo per restare svegli: l'esenzione dall'ottimizzazione della batteria, che Android concede se la chiedi. Però la domanda te la fa a modo suo, "Interrompere l'ottimizzazione dell'utilizzo della batteria?", senza contesto e senza un perché. Adesso BeeBEEP parla per primo. Con parole sue spiega che, per ricevere i messaggi a schermo spento, deve restare in esecuzione, e ti chiede di scegliere Consenti. Poi chiede Android. Una volta sola, al primo avvio, e mai più.
Ma serve? Ho forzato a mano Doze, il sonno più profondo di Android. Con il servizio attivo, un messaggio è arrivato in 0,125 secondi senza l'esenzione e in 0,136 con l'esenzione, ognuno con la sua notifica e il suo suono. Quindi, con il servizio, no. Senza il servizio è tutto: con l'esenzione sono arrivati tutti e sei i messaggi, senza nemmeno uno.
Un telefono che non dice niente
Questa era la parte difficile, e non l'avevo vista arrivare.
Un computer già collegato al telefono lo tiene raggiungibile da solo. Ogni dieci secondi circa gli manda un piccolo messaggio per tenere vivo il collegamento, il messaggio sveglia il telefono, il telefono risponde. Si fanno compagnia.
Ma un computer che si accende mentre il telefono dorme, e non l'ha mai incontrato, prima deve sentirlo. E un telefono che dorme non dice niente. In mezz'ora senza nessuno collegato è rimasto sveglio 54 secondi in tutto. Ho acceso un computer da solo lì accanto e ho aspettato. Venti minuti, e non l'ha mai trovato.
Ecco cosa vuol dire davvero non avere un server. In un messenger con un server c'è sempre qualcuno che sa chi è dove. Qui nessuno fa le presentazioni. Due dispositivi sullo stesso tavolo, e non sanno l'uno dell'altro.
Dodici secondi di troppo
La prima risposta è stata una sveglia periodica. Ogni dieci minuti un allarme di Android sveglia BeeBEEP, che tiene il processore per dodici secondi, si annuncia e controlla i suoi collegamenti.
Funzionava: un computer nuovo ha trovato il telefono addormentato in 61 secondi, a una sveglia. Ma il conto era più che raddoppiato, 0,72 mAh all'ora contro 0,32. E dei miei dieci minuti ad Android importava poco: le sveglie sono arrivate quattro volte in un'ora, a distanza di 12,6-17,5 minuti l'una dall'altra. Sotto Doze, un allarme che non è esatto viene distribuito come pare al sistema.
Dov'era finita la batteria? Sono andato a spulciare i conti. Quasi tutta nel tenere il processore, e ogni sveglia si teneva tutti i suoi dodici secondi, anche se il suo lavoro ne richiede circa quattro. Una sveglia costava circa 0,12 mAh, e quasi tutto era attesa.
Così la sveglia ha imparato ad andarsene appena ha finito, e i dodici secondi sono rimasti solo come limite. Ho misurato di nuovo, nello stesso modo. Le quattro sveglie hanno tenuto il processore per 2,0, 6,2, 2,1 e 2,0 secondi: 0,068 mAh per tutte e quattro, contro 0,47. Il prezzo di una sveglia è sceso da 0,12 mAh a 0,017.
Il costo non era mai stato il lavoro. Era l'attesa.
Nella stessa prova la sveglia mi ha mostrato cosa compra. Al ventunesimo minuto un computer ha perso il telefono, per un motivo che non sono riuscito a vedere. La sveglia successiva è arrivata 3 minuti e 51 secondi dopo, ha annunciato il telefono, e il collegamento è tornato subito. Il giorno prima, senza sveglia, una perdita dello stesso tipo era durata dieci minuti e mezzo.
Quindi la sveglia resta, attiva di default. Non fingerò che renda sempre tutto più veloce. Una volta, in un'ora senza sveglie, un computer nuovo ha trovato il telefono in 60 secondi, per puro caso. Nell'ultima prova un nuovo arrivato si è collegato dopo otto minuti e mezzo, grazie a un annuncio che il telefono aveva mandato tra due sveglie. Quello che la sveglia compra non è la velocità. È un limite: un computer nuovo trova un telefono addormentato entro un intervallo, dai dieci ai diciotto minuti sotto Doze, invece di forse mai, e un collegamento perso torna alla sveglia successiva. Tutto questo riguarda il Wi-Fi. Il Bluetooth non c'entra.
Il Bluetooth che non voleva dormire
Negli stessi conti c'era una sorpresa. Una riga che non mi aspettavo: il Bluetooth, in onda, a cercare, per tutta l'ora in cui il telefono dormiva. 0,12 mAh, il 30% di tutto quello che BeeBEEP aveva speso.
Quando lo schermo si spegneva con BeeBEEP aperto, Android segnalava due cambi a pochi millisecondi l'uno dall'altro: "sospeso", poi "inattivo". BeeBEEP prendeva "inattivo" per "ancora in primo piano", e continuava a cercare dispositivi vicini, su un telefono lasciato da solo su un tavolo. Adesso solo "attivo" riporta BeeBEEP in primo piano. Un'altra lunga prova sul telefono sarà la verifica finale.
Nessun test l'avrebbe trovato. Solo un telefono vero, misurato, mostra una cosa del genere.
Le piccole bugie del sonno
Lasciato in pace, il telefono mi ha raccontato anche altro.
A schermo spento il Wi-Fi smette di ascoltare gli annunci dei computer, dopo 12-41 secondi, mentre il processore è ancora sveglio. Il Wi-Fi li filtra per conto suo.
Nel sonno profondo i timer si fermano. Il piccolo messaggio con cui BeeBEEP tiene vivo un collegamento, previsto ogni 5-7 secondi, partiva più o meno una volta ogni 46. Il collegamento viveva dei messaggi del computer, che arrivando svegliano il telefono.
La mia preferita: un sonno scambiato per qualcuno che sposta l'orologio. BeeBEEP tiene d'occhio l'ora, nel caso qualcuno la cambi, e in mezz'ora si è lamentato 152 volte. Ho sommato i salti che aveva visto: 1565 secondi, esattamente i 26 minuti che il telefono aveva passato in sonno profondo. L'orologio con cui confrontava si ferma quando il telefono dorme, quello di sistema no. BeeBEEP guardava il telefono sognare e gridava alla truffa. Corretto.
Un telefono appena reinstallato e un computer partiti nello stesso secondo si sono chiamati a vicenda; la radio ha perso entrambe le chiamate, e nessuno ha più richiamato. Corretto: dopo, cinque riavvii accanto a un computer che si accendeva si sono collegati da soli, in un tempo tra mezzo secondo e tre.
E dietro la schermata di blocco non parte niente. Lanciato con il telefono bloccato, BeeBEEP esisteva, ma non ha eseguito una sola riga fino allo sblocco col volto, 2 minuti e 16 secondi dopo.
Il Bluetooth, su radio vere
L'articolo precedente finiva con il Bluetooth: un modo per trovarsi senza internet e senza server, tra le pareti di un ufficio. Poi, per la prima volta, ha funzionato tra dispositivi veri.
Un computer ha riconosciuto il telefono come un contatto vicino solo via Bluetooth, senza che nessuno premesse cerca. Da quando l'ha chiamato a quando l'ha mostrato vicino: 4,85 secondi. Sulla carta avevo stimato qualche centinaio di millisecondi; la sola connessione della radio ne ha chiesti tremila. Ma funzionava.
Una volta. I tentativi successivi, undici, sono andati tutti a vuoto. Quando si chiude l'ultima connessione, il codice Android di Qt chiude il server Bluetooth del telefono, e BeeBEEP, ripartendo, ne apriva uno nuovo, vuoto. Il telefono continuava ad annunciare BeeBEEP senza niente dietro, come un negozio con l'insegna accesa e nessuno dentro. La causa è stata trovata lo stesso giorno: adesso dopo ogni disconnessione si costruisce un server nuovo.
Dopo ogni connessione il telefono trasmette anche da un nuovo indirizzo casuale: BeeBEEP riavvia il suo annuncio, e Android dà a ogni avvio un indirizzo nuovo. Sarebbe bello dire che è questo a impedire che qualcuno ti segua, ma non è tutta la storia. Il piccolo segnale che c'è dietro, 16 byte, resta lo stesso per quindici minuti, e in quei quindici minuti uno scanner potrebbe capire che gli indirizzi sono di un solo telefono. Quello che ti protegge è il segnale stesso: ogni quindici minuti cambia, e per uno sconosciuto non ha mai significato niente.
E la lezione del giorno è arrivata dal computer. Quello con Linux non riusciva proprio a trasmettere. Un dispositivo può rispondere a una ricerca con un secondo pacchetto breve, la scan response, ma il codice Bluetooth di Qt su Linux non sa mandarlo. Così infilava entrambi gli identificativi di BeeBEEP, il servizio e il segnale, in un solo annuncio: 40 byte, dove uno classico ne ammette 31. L'adattatore di un computer lo rifiutava. Uno più recente lo accettava come annuncio "esteso", che la ricerca di Android non ascolta nemmeno. Avrebbe fallito in silenzio, il modo peggiore di fallire. Sulla radio simulata dei test era passato tutto.
La risposta: dove il sistema non può mandare una scan response, il segnale non va in onda, e il telefono riconosce quel computer dal suo indirizzo, come fa già con un iPhone. Costa una breve lettura ogni quindici minuti, e niente in privacy, perché un computer così trasmette già da un indirizzo fisso.
Tre decimi di milliampere-ora
Un server mi avrebbe risparmiato quasi tutto questo. Bussa, il telefono si sveglia, fine della storia. Senza, BeeBEEP deve restare abbastanza sveglio da farsi trovare e abbastanza addormentato da non farsi notare, e il confine tra le due cose si traccia in frazioni di milliampere-ora.
Adesso so dov'è quel confine. In background, collegato, a schermo spento, BeeBEEP costa circa 0,3 mAh all'ora, lo 0,15% della batteria al giorno, e i messaggi arrivano in meno di un secondo. Una sveglia costa 0,017.
Un telefono in tasca dorme, avevo scritto. Dorme ancora. Ma adesso ti sente.
