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}