1 package com.android.cts.verifier.jobscheduler; 2 3 import android.annotation.TargetApi; 4 import android.app.job.JobInfo; 5 import android.content.BroadcastReceiver; 6 import android.content.Context; 7 import android.content.Intent; 8 import android.content.IntentFilter; 9 import android.net.ConnectivityManager; 10 import android.net.NetworkInfo; 11 import android.os.AsyncTask; 12 import android.os.Bundle; 13 import android.util.Log; 14 import android.widget.Button; 15 import android.widget.ImageView; 16 17 import com.android.cts.verifier.R; 18 19 /** 20 * The majority of the connectivity constraints are done in the device-side test app 21 * android.jobscheduler.cts.deviceside. However a manual tester is required to completely turn off 22 * connectivity on the device in order to verify that jobs with connectivity constraints will not 23 * run in the absence of an internet connection. 24 */ 25 @TargetApi(21) 26 public class ConnectivityConstraintTestActivity extends ConstraintTestActivity { 27 private static final String TAG = "ConnectivityConstraintTestActivity"; 28 private static final int ANY_CONNECTIVITY_JOB_ID = 29 ConnectivityConstraintTestActivity.class.hashCode() + 0; 30 private static final int UNMETERED_CONNECTIVITY_JOB_ID = 31 ConnectivityConstraintTestActivity.class.hashCode() + 1; 32 private static final int NO_CONNECTIVITY_JOB_ID = 33 ConnectivityConstraintTestActivity.class.hashCode() + 2; 34 private static final int NO_CONNECTIVITY_JOB_ID_2 = 35 ConnectivityConstraintTestActivity.class.hashCode() + 3; 36 37 @Override onCreate(Bundle savedInstanceState)38 protected void onCreate(Bundle savedInstanceState) { 39 super.onCreate(savedInstanceState); 40 41 // Set up the UI. 42 setContentView(R.layout.js_connectivity); 43 setPassFailButtonClickListeners(); 44 setInfoResources(R.string.js_connectivity_test, R.string.js_connectivity_instructions, -1); 45 mStartButton = (Button) findViewById(R.id.js_connectivity_start_test_button); 46 47 // Disable test start if there is data connectivity. 48 mStartButton.setEnabled(isDataUnavailable()); 49 // Register receiver to listen for connectivity changes. 50 IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); 51 registerReceiver(mConnectivityChangedReceiver, intentFilter); 52 53 } 54 55 @Override onDestroy()56 protected void onDestroy() { 57 super.onDestroy(); 58 unregisterReceiver(mConnectivityChangedReceiver); 59 } 60 61 @Override startTestImpl()62 protected void startTestImpl() { 63 new TestConnectivityConstraint().execute(); 64 } 65 66 /** Ensure that there's no connectivity before we allow the test to start. */ 67 BroadcastReceiver mConnectivityChangedReceiver = new BroadcastReceiver() { 68 @Override 69 public void onReceive(Context context, Intent intent) { 70 Log.d(TAG, "received: " + intent); 71 String extras = ""; 72 for (String name : intent.getExtras().keySet()) { 73 extras += " |" + name + " " + intent.getExtras().get(name) + "|"; 74 75 } 76 Log.d(TAG, "extras: " + extras); 77 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { 78 // Only enable the test when we know there is no connectivity. 79 mStartButton.setEnabled(isDataUnavailable()); 80 } 81 } 82 }; 83 testUnmeteredConstraintFails_noConnectivity()84 private void testUnmeteredConstraintFails_noConnectivity() { 85 testConnectivityConstraintFailsImpl( 86 JobInfo.NETWORK_TYPE_UNMETERED, UNMETERED_CONNECTIVITY_JOB_ID); 87 } 88 testAnyConnectivityConstraintFails_noConnectivity()89 private void testAnyConnectivityConstraintFails_noConnectivity() { 90 testConnectivityConstraintFailsImpl(JobInfo.NETWORK_TYPE_ANY, ANY_CONNECTIVITY_JOB_ID); 91 } 92 testNoConnectivityConstraintExecutes_noConnectivity()93 private void testNoConnectivityConstraintExecutes_noConnectivity() { 94 JobInfo testJob1 = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID, mMockComponent) 95 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE) 96 .setOverrideDeadline(100000L) // Will not expire. 97 .build(); 98 JobInfo testJob2 = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID_2, mMockComponent) 99 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE) 100 .setOverrideDeadline(100000L) // Will not expire. 101 .build(); 102 103 mTestEnvironment.setUp(); 104 mTestEnvironment.setExpectedExecutions(2); 105 106 mJobScheduler.schedule(testJob1); 107 mJobScheduler.schedule(testJob2); 108 109 boolean testPassed; 110 try { 111 testPassed = mTestEnvironment.awaitExecution(); 112 } catch (InterruptedException e) { 113 testPassed = false; 114 } 115 runOnUiThread( 116 new ConnectivityConstraintTestResultRunner(NO_CONNECTIVITY_JOB_ID, testPassed)); 117 } 118 testConnectivityConstraintFailsImpl(int requiredNetworkType, int jobId)119 private void testConnectivityConstraintFailsImpl(int requiredNetworkType, int jobId) { 120 // Use arguments provided to construct job with required connectivity constraint. 121 JobInfo testJob = new JobInfo.Builder(jobId, mMockComponent) 122 .setRequiredNetworkType(requiredNetworkType) 123 .build(); 124 125 mTestEnvironment.setUp(); 126 mTestEnvironment.setExpectedExecutions(0); 127 128 mJobScheduler.schedule(testJob); 129 130 boolean testPassed; 131 try { 132 testPassed = mTestEnvironment.awaitTimeout(); 133 } catch (InterruptedException e) { 134 testPassed = false; 135 } 136 runOnUiThread( 137 new ConnectivityConstraintTestResultRunner(jobId, testPassed)); 138 } 139 140 /** Query the active network connection and return if there is no data connection. */ isDataUnavailable()141 private boolean isDataUnavailable() { 142 final ConnectivityManager cm = 143 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 144 final NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 145 146 return (activeNetwork == null) || 147 !activeNetwork.isConnectedOrConnecting(); 148 } 149 150 private class TestConnectivityConstraint extends AsyncTask<Void, Void, Void> { 151 152 @Override doInBackground(Void... voids)153 protected Void doInBackground(Void... voids) { 154 testUnmeteredConstraintFails_noConnectivity(); 155 testAnyConnectivityConstraintFails_noConnectivity(); 156 testNoConnectivityConstraintExecutes_noConnectivity(); 157 158 notifyTestCompleted(); 159 return null; 160 } 161 } 162 163 private class ConnectivityConstraintTestResultRunner extends TestResultRunner { ConnectivityConstraintTestResultRunner(int jobId, boolean testPassed)164 ConnectivityConstraintTestResultRunner(int jobId, boolean testPassed) { 165 super(jobId, testPassed); 166 } 167 168 @Override run()169 public void run() { 170 ImageView view; 171 if (mJobId == ANY_CONNECTIVITY_JOB_ID) { 172 view = (ImageView) findViewById(R.id.connectivity_off_test_any_connectivity_image); 173 } else if (mJobId == UNMETERED_CONNECTIVITY_JOB_ID) { 174 view = (ImageView) findViewById(R.id.connectivity_off_test_unmetered_image); 175 } else if (mJobId == NO_CONNECTIVITY_JOB_ID) { 176 view = (ImageView) findViewById(R.id.connectivity_off_test_no_connectivity_image); 177 } else { 178 noteInvalidTest(); 179 return; 180 } 181 view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error); 182 } 183 } 184 185 } 186