1 package com.android.cts.content; 2 3 import android.accounts.Account; 4 import android.accounts.AccountManager; 5 import android.accounts.AuthenticatorException; 6 import android.accounts.OperationCanceledException; 7 import android.app.Activity; 8 import android.content.ContentResolver; 9 import android.content.Context; 10 import android.content.SyncRequest; 11 import android.content.pm.PackageManager; 12 import android.content.res.Configuration; 13 import android.net.ConnectivityManager; 14 import android.net.NetworkInfo; 15 import android.os.Bundle; 16 import android.os.Process; 17 import android.os.SystemClock; 18 import android.support.test.uiautomator.UiDevice; 19 import android.util.Log; 20 21 import androidx.annotation.NonNull; 22 import androidx.test.InstrumentationRegistry; 23 24 import com.android.compatibility.common.util.SystemUtil; 25 26 import java.io.IOException; 27 28 public class Utils { 29 private static final String LOG_TAG = Utils.class.getSimpleName(); 30 31 public static final long SYNC_TIMEOUT_MILLIS = 20000; // 20 sec 32 public static final String TOKEN_TYPE_REMOVE_ACCOUNTS = "TOKEN_TYPE_REMOVE_ACCOUNTS"; 33 public static final String SYNC_ACCOUNT_TYPE = "com.stub"; 34 public static final String ALWAYS_SYNCABLE_AUTHORITY = "com.android.cts.stub.provider"; 35 public static final String NOT_ALWAYS_SYNCABLE_AUTHORITY = "com.android.cts.stub.provider2"; 36 37 public static boolean hasDataConnection() { 38 ConnectivityManager connectivityManager = getContext().getSystemService( 39 ConnectivityManager.class); 40 NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); 41 return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); 42 } 43 44 public static boolean hasNotificationSupport() { 45 return !getContext().getPackageManager() 46 .hasSystemFeature(PackageManager.FEATURE_LEANBACK); 47 } 48 49 public static Context getContext() { 50 return InstrumentationRegistry.getInstrumentation().getContext(); 51 } 52 53 public static boolean isWatch() { 54 return (getContext().getResources().getConfiguration().uiMode 55 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH; 56 } 57 58 public static UiDevice getUiDevice() { 59 return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 60 } 61 62 public static void waitForSyncManagerAccountChangeUpdate() { 63 // Wait for the sync manager to be notified for the new account. 64 // Unfortunately, there is no way to detect this event, sigh... 65 SystemClock.sleep(SYNC_TIMEOUT_MILLIS); 66 } 67 68 public static void allowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException { 69 // Allow us to run in the background 70 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 71 "cmd deviceidle whitelist +" + getContext().getPackageName()); 72 // Allow us to use data in the background 73 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 74 "cmd netpolicy add restrict-background-whitelist " + Process.myUid()); 75 } 76 77 public static void disallowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException { 78 // Allow us to run in the background 79 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 80 "cmd deviceidle whitelist -" + getContext().getPackageName()); 81 // Allow us to use data in the background 82 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 83 "cmd netpolicy remove restrict-background-whitelist " + Process.myUid()); 84 } 85 86 public static class ClosableAccount implements AutoCloseable { 87 public final Account account; 88 89 private ClosableAccount(@NonNull Account account) { 90 this.account = account; 91 } 92 93 @Override 94 public void close() throws Exception { 95 AccountManager accountManager = getContext().getSystemService(AccountManager.class); 96 97 accountManager.getAuthToken(account, TOKEN_TYPE_REMOVE_ACCOUNTS, null, false, null, 98 null); 99 } 100 } 101 102 public static ClosableAccount withAccount(@NonNull Activity activity) 103 throws AuthenticatorException, OperationCanceledException, IOException { 104 AccountManager accountManager = getContext().getSystemService(AccountManager.class); 105 Bundle result = accountManager.addAccount(SYNC_ACCOUNT_TYPE, null, null, null, 106 activity, null, null).getResult(); 107 Account addedAccount = new Account( 108 result.getString(AccountManager.KEY_ACCOUNT_NAME), 109 result.getString(AccountManager.KEY_ACCOUNT_TYPE)); 110 Log.i(LOG_TAG, "Added account " + addedAccount); 111 112 waitForSyncManagerAccountChangeUpdate(); 113 114 return new ClosableAccount(addedAccount); 115 } 116 117 public static SyncRequest requestSync(String authority) { 118 Bundle extras = new Bundle(); 119 extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); 120 extras.putBoolean(ContentResolver.SYNC_EXTRAS_PRIORITY, true); 121 extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); 122 SyncRequest request = new SyncRequest.Builder() 123 .setSyncAdapter(null, authority) 124 .syncOnce() 125 .setExtras(extras) 126 .setExpedited(true) 127 .setManual(true) 128 .build(); 129 ContentResolver.requestSync(request); 130 131 return request; 132 } 133 } 134