ConnTestActivity.java revision 686bb2d337517b0b3f4ff4a6062c84a3ee730307
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.servicestests.apps.conntestapp; 18 19import android.app.Activity; 20import android.content.BroadcastReceiver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.content.pm.PackageManager; 25import android.net.ConnectivityManager; 26import android.net.NetworkInfo; 27import android.os.AsyncTask; 28import android.os.Bundle; 29import android.os.RemoteException; 30import android.util.Log; 31 32import com.android.servicestests.aidl.INetworkStateObserver; 33 34import java.net.HttpURLConnection; 35import java.net.URL; 36 37public class ConnTestActivity extends Activity { 38 private static final String TAG = ConnTestActivity.class.getSimpleName(); 39 40 private static final String TEST_PKG = ConnTestActivity.class.getPackage().getName(); 41 private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH"; 42 private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer"; 43 44 private static final int NETWORK_TIMEOUT_MS = 5 * 1000; 45 46 private static final String NETWORK_STATUS_TEMPLATE = "%s|%s|%s|%s|%s"; 47 48 private BroadcastReceiver finishCommandReceiver = null; 49 50 @Override 51 public void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 54 notifyNetworkStateObserver(); 55 56 finishCommandReceiver = new BroadcastReceiver() { 57 @Override 58 public void onReceive(Context context, Intent intent) { 59 ConnTestActivity.this.finish(); 60 } 61 }; 62 registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY)); 63 } 64 65 @Override 66 public void onStop() { 67 if (finishCommandReceiver != null) { 68 unregisterReceiver(finishCommandReceiver); 69 } 70 super.onStop(); 71 } 72 73 private void notifyNetworkStateObserver() { 74 if (getIntent() == null) { 75 return; 76 } 77 78 final Bundle extras = getIntent().getExtras(); 79 if (extras == null) { 80 return; 81 } 82 final INetworkStateObserver observer = INetworkStateObserver.Stub.asInterface( 83 extras.getBinder(EXTRA_NETWORK_STATE_OBSERVER)); 84 if (observer != null) { 85 AsyncTask.execute(() -> { 86 try { 87 observer.onNetworkStateChecked(checkNetworkStatus(ConnTestActivity.this)); 88 } catch (RemoteException e) { 89 Log.e(TAG, "Error occured while notifying the observer: " + e); 90 } 91 }); 92 } 93 } 94 95 /** 96 * Checks whether the network is available and return a string which can then be send as a 97 * result data for the ordered broadcast. 98 * 99 * <p> 100 * The string has the following format: 101 * 102 * <p><pre><code> 103 * NetinfoState|NetinfoDetailedState|RealConnectionCheck|RealConnectionCheckDetails|Netinfo 104 * </code></pre> 105 * 106 * <p>Where: 107 * 108 * <ul> 109 * <li>{@code NetinfoState}: enum value of {@link NetworkInfo.State}. 110 * <li>{@code NetinfoDetailedState}: enum value of {@link NetworkInfo.DetailedState}. 111 * <li>{@code RealConnectionCheck}: boolean value of a real connection check (i.e., an attempt 112 * to access an external website. 113 * <li>{@code RealConnectionCheckDetails}: if HTTP output core or exception string of the real 114 * connection attempt 115 * <li>{@code Netinfo}: string representation of the {@link NetworkInfo}. 116 * </ul> 117 * 118 * For example, if the connection was established fine, the result would be something like: 119 * <p><pre><code> 120 * CONNECTED|CONNECTED|true|200|[type: WIFI[], state: CONNECTED/CONNECTED, reason: ...] 121 * </code></pre> 122 */ 123 private String checkNetworkStatus(Context context) { 124 final ConnectivityManager cm = 125 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 126 final String address = "http://example.com"; 127 final NetworkInfo networkInfo = cm.getActiveNetworkInfo(); 128 Log.d(TAG, "Running checkNetworkStatus() on thread " 129 + Thread.currentThread().getName() + " for UID " + getUid(context) 130 + "\n\tactiveNetworkInfo: " + networkInfo + "\n\tURL: " + address); 131 boolean checkStatus = false; 132 String checkDetails = "N/A"; 133 try { 134 final URL url = new URL(address); 135 final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 136 conn.setReadTimeout(NETWORK_TIMEOUT_MS); 137 conn.setConnectTimeout(NETWORK_TIMEOUT_MS / 2); 138 conn.setRequestMethod("GET"); 139 conn.setDoInput(true); 140 conn.connect(); 141 final int response = conn.getResponseCode(); 142 checkStatus = true; 143 checkDetails = "HTTP response for " + address + ": " + response; 144 } catch (Exception e) { 145 checkStatus = false; 146 checkDetails = "Exception getting " + address + ": " + e; 147 } 148 Log.d(TAG, checkDetails); 149 final String state, detailedState; 150 if (networkInfo != null) { 151 state = networkInfo.getState().name(); 152 detailedState = networkInfo.getDetailedState().name(); 153 } else { 154 state = detailedState = "null"; 155 } 156 final String status = String.format(NETWORK_STATUS_TEMPLATE, state, detailedState, 157 Boolean.valueOf(checkStatus), checkDetails, networkInfo); 158 Log.d(TAG, "Offering " + status); 159 return status; 160 } 161 162 private int getUid(Context context) { 163 final String packageName = context.getPackageName(); 164 try { 165 return context.getPackageManager().getPackageUid(packageName, 0); 166 } catch (PackageManager.NameNotFoundException e) { 167 throw new IllegalStateException("Could not get UID for " + packageName, e); 168 } 169 } 170}