Esta página descreve aspectos importantes do teste de vários usuários na plataforma Android. Para informações sobre como implementar o suporte a vários usuários, consulte Suporte a vários usuários.
Caminhos de dispositivos
A tabela a seguir lista vários caminhos de dispositivos e como eles são resolvidos. Todos os valores na coluna Caminho são um armazenamento em sandbox específico do usuário. O armazenamento do Android mudou com o tempo. Leia a documentação sobre Armazenamento para mais informações.
| Caminho | Caminho do sistema (opcional) | Finalidade |
|---|---|---|
/data/user/{userId}/{app.path}
|
/data/data
|
Armazenamento de apps |
/storage/emulated/{userId}
|
/sdcard
|
Armazenamento interno compartilhado |
/data/media/{userId}
|
none | Dados de mídia do usuário (por exemplo, músicas, vídeos) |
/data/system/users/{userId}
|
none | Configuração/estado do sistema por usuário
Acessível apenas por apps do sistema |
Confira um exemplo de uso de um caminho específico do usuário:
# to access user 10's private application data for app com.bar.foo:
$ adb shell ls /data/user/10/com.bar.foo/
Interações do adb entre usuários
Vários comandos do adb são úteis ao lidar com vários usuários. Alguns desses comandos são compatíveis apenas com o Android 9 e versões mais recentes:
adb shell am instrument --user <userId>executa um teste de instrumentação em um usuário específico. Por padrão, isso usa o usuário atual.- O
adb install --user <userId>instala um pacote para um usuário específico. Para garantir que um pacote seja instalado para todos os usuários, chame esse para cada usuário. - O
adb uninstall --user <userId>desinstala um pacote para um usuário específico. Chame sem a flag--userpara desinstalar para todos os usuários. adb shell am get-current-userrecebe o ID do usuário atual (em primeiro plano).- O
adb shell pm list usersrecebe uma lista de todos os usuários atuais. adb shell pm create-usercria um novo usuário e retorna o ID.adb shell pm remove-userremove um usuário específico por ID.adb shell pm disable --user <userId>desativa um pacote para um usuário específico.adb shell pm enable --user <userId>permite um pacote para um usuário específico.- O
adb shell pm list packages --user <userId>lista pacotes (-epara ativados,-dpara desativados) de um usuário específico. Por padrão, isso sempre lista para o usuário do sistema.
As informações a seguir ajudam a explicar como o adb se comporta com vários usuários:
O
adb(ou mais precisamente o daemonadbd) sempre é executado como o usuário do sistema (ID do usuário = 0) independente de qual usuário está ativo. Portanto, caminhos de dispositivos que dependem do usuário (como/sdcard/) sempre são resolvidos como o usuário do sistema. Consulte Caminhos de dispositivo para mais detalhes.Se um usuário padrão não for especificado, cada subcomando
adbterá um usuário diferente. A prática recomendada é recuperar o ID do usuário comam get-current-usere usar explicitamente--user <userId>para qualquer comando compatível. As flags explícitas do usuário não eram compatíveis com todos os comandos até o Android 9.O acesso aos caminhos
/sdcardde usuários secundários é negado a partir do Android 9. Consulte Provedor de conteúdo para dados de vários usuários para detalhes sobre como recuperar arquivos durante o teste.
Provedor de conteúdo para dados de vários usuários
Como o adb é executado como usuário do sistema e os dados são isolados em sandbox no Android 9 e versões mais recentes, é necessário usar provedores de conteúdo para enviar ou
extrair dados de teste de um usuário que não seja do sistema. Isso não é necessário se:
O
adbdestá sendo executado como raiz (peloadb root), o que só é possível usando buildsuserdebugouusereng.Você está usando o
ITestDevicedo Trade Federation (Tradefed) para enviar ou extrair os arquivos. Nesse caso, use caminhos/sdcard/na configuração de teste. Por exemplo, consulte o código-fonte depushFileemNativeDevice.java.
Quando um provedor de conteúdo está sendo executado no usuário secundário, é possível acessá-lo usando o comando adb shell content com os parâmetros user, uri e outros especificados.
Solução alternativa para desenvolvedores de apps
Interaja com arquivos de teste usando adb content e uma instância de
ContentProvider,
em vez do comando push ou pull.
- Crie uma instância de
ContentProviderhospedada pelo app que possa veicular e armazenar arquivos quando necessário. Use o armazenamento interno do app. - Use os comandos
adb shell contentreadouwritepara enviar ou extrair os arquivos.
Solução alternativa para arquivos de mídia
Para enviar arquivos de mídia à partição de mídia do cartão SD, use as APIs públicas MediaStore. Exemplo:
# push MVIMG_20190129_142956.jpg to /storage/emulated/10/Pictures
# step 1
$ adb shell content insert --user 10 --uri content://media/external/images/media/ --bind _display_name:s:foo.jpg
# step 2
$ adb shell content query --user 10 --projection _id --uri content://media/external/images/media/ --where "_display_name=\'foo.jpg\'"
# step 3
$ adb shell content write --user 10 --uri content://media/external/images/media/8022 < MVIMG_20190129_142956.jpg
Instalar um provedor de conteúdo genérico
Instale e use um provedor de conteúdo que leia e grave arquivos no caminho /sdcard específico do usuário.
Crie o TradefedContentProvider.apk da origem usando
make TradefedContentProvider:
```
# install content provider apk
$ adb install --user 10 -g TradefedContentProvider.apk
# pull some_file.txt
$ adb shell content read --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt > local_file.txt
# push local_file.txt
$ adb shell content write --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt < local_file.txt
```
Suporte multiusuário do Trade Federation
O Tradefed é o arcabouço de testes oficial do Android. Esta seção resume alguns dos recursos integrados do Tradefed para cenários de teste multiusuário.
Verificadores de status
Os verificadores de status do sistema (SSCs, na sigla em inglês) são executados antes dos preparadores de destino, e a limpeza deles é executada depois desses preparadores.
UserChecker
é definido explicitamente para ajudar os desenvolvedores ao testar vários usuários. Ele rastreia
se um teste mudou o estado dos usuários no dispositivo (por exemplo,
criou usuários sem removê-los na desmontagem). Além disso, se user-cleanup
estiver definido, ele tentará limpar automaticamente após o teste, mas ainda
fornecerá erros úteis para que o teste possa ser corrigido.
<system_checker class="com.android.tradefed.suite.checker.UserChecker" >
<option name="user-cleanup" value="true" />
</system_checker>
Preparador de destino
Os preparadores de destino geralmente são usados para configurar um dispositivo com uma configuração específica. No caso de testes multiusuário, os preparadores podem ser usados para criar usuários de um tipo específico e alternar para outros usuários.
Para tipos de dispositivos que não têm um usuário secundário, use
CreateUserPreparer para criar e alternar para um usuário secundário em
AndroidTest.xml. Ao final do teste, o preparador volta e exclui o usuário secundário.
<target_preparer
class="com.google.android.tradefed.targetprep.CreateUserPreparer" >
</target_preparer>
Se o tipo de usuário que você quer já existir no dispositivo, use
SwitchUserTargetPreparer para mudar para o usuário atual. Os valores comuns para user-type incluem system ou secondary.
<target_preparer
class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
<option name="user-type" value="secondary" />
</target_preparer>
Testes controlados pelo host
Em alguns casos, um teste precisa trocar de usuário durante o teste. Não
faça a troca em um framework de teste do lado do dispositivo, como o
UI Automator,
porque o processo de teste pode ser encerrado a qualquer momento. Em vez disso, use um framework de teste do lado do host, como o framework de teste orientado por host do Tradefed,
que dá acesso ao
ITestDevice,
permitindo qualquer manipulação do usuário necessária.
Use UserChecker (descrito em
Verificadores de status) para testes orientados por host que mudam
o estado do usuário, porque ele garante que o teste seja limpo corretamente depois.