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