package br.carinha.rosto; import android.Manifest; import android.app.Activity; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.app.admin.SystemUpdatePolicy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import android.os.Build; import android.provider.Settings; import android.util.Log; /** * Modo quiosque: com o app como dono do aparelho, a carinha é a tela inicial, * abre sozinha ao ligar e ninguém sai dela (sem barra de status, sem tela de bloqueio). * Sem ser dono, tudo aqui é ignorado e o app funciona como antes. */ public final class Quiosque { private static final String TAG = "CarinhaQuiosque"; /** Pausado pelo menu para manutenção; volta sozinho quando o celular reinicia. */ private static boolean pausado; private Quiosque() { } private static DevicePolicyManager dpm(Context c) { return (DevicePolicyManager) c.getSystemService(Context.DEVICE_POLICY_SERVICE); } private static ComponentName admin(Context c) { return new ComponentName(c, Admin.class); } public static boolean dono(Context c) { DevicePolicyManager d = dpm(c); return d != null && d.isDeviceOwnerApp(c.getPackageName()); } public static boolean pausado() { return pausado; } /** Chamado no onResume: reaplica as travas (idempotente). */ public static void aplicar(Activity a) { if (pausado || !dono(a)) return; DevicePolicyManager d = dpm(a); ComponentName adm = admin(a); String pacote = a.getPackageName(); try { d.setLockTaskPackages(adm, new String[]{pacote}); // a carinha é a tela inicial: botão Home e o fim do boot caem nela IntentFilter inicio = new IntentFilter(Intent.ACTION_MAIN); inicio.addCategory(Intent.CATEGORY_HOME); inicio.addCategory(Intent.CATEGORY_DEFAULT); d.addPersistentPreferredActivity(adm, inicio, new ComponentName(a, MainActivity.class)); // tela ligada enquanto estiver na tomada, USB ou carregador sem fio d.setGlobalSetting(adm, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, String.valueOf( BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB | BatteryManager.BATTERY_PLUGGED_WIRELESS)); if (Build.VERSION.SDK_INT >= 23) { d.setKeyguardDisabled(adm, true); d.setStatusBarDisabled(adm, true); // atualização do sistema só de madrugada (3h–5h), nunca no meio do dia d.setSystemUpdatePolicy(adm, SystemUpdatePolicy.createWindowedInstallPolicy(180, 300)); // câmera e microfone sem perguntar, inclusive depois de reinstalar o app for (String p : new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}) d.setPermissionGrantState(adm, pacote, p, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); } // o botão Ligar continua abrindo o menu de desligar/reiniciar if (Build.VERSION.SDK_INT >= 28) d.setLockTaskFeatures(adm, DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS); if (!travado(a)) a.startLockTask(); } catch (Exception e) { Log.e(TAG, "aplicar: " + e); } } /** Solta a tela até o próximo reinício, para mexer nas configurações do Android. */ public static void pausar(Activity a) { if (!dono(a)) return; pausado = true; DevicePolicyManager d = dpm(a); ComponentName adm = admin(a); try { if (travado(a)) a.stopLockTask(); d.clearPackagePersistentPreferredActivities(adm, a.getPackageName()); if (Build.VERSION.SDK_INT >= 23) { d.setKeyguardDisabled(adm, false); d.setStatusBarDisabled(adm, false); } } catch (Exception e) { Log.e(TAG, "pausar: " + e); } } /** Volta a travar sem precisar reiniciar. */ public static void retomar(Activity a) { pausado = false; aplicar(a); } /** Deixa de ser dono do aparelho de vez (para desinstalar ou trocar de app). */ @SuppressWarnings("deprecation") public static void remover(Activity a) { if (!dono(a)) return; pausar(a); try { dpm(a).clearDeviceOwnerApp(a.getPackageName()); } catch (Exception e) { Log.e(TAG, "remover: " + e); } } private static boolean travado(Activity a) { ActivityManager am = (ActivityManager) a.getSystemService(Context.ACTIVITY_SERVICE); if (am == null) return false; if (Build.VERSION.SDK_INT >= 23) return am.getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE; return am.isInLockTaskMode(); } }