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.net.INetworkPolicyManager;
25import android.os.AsyncTask;
26import android.os.Bundle;
27import android.os.INetworkManagementService;
28import android.os.Process;
29import android.os.RemoteException;
30import android.os.ServiceManager;
31import android.util.Log;
32
33import com.android.internal.annotations.GuardedBy;
34import com.android.servicestests.aidl.INetworkStateObserver;
35
36public class ConnTestActivity extends Activity {
37    private static final String TAG = ConnTestActivity.class.getSimpleName();
38
39    private static final String TEST_PKG = ConnTestActivity.class.getPackage().getName();
40    private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH";
41    private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
42
43    private static final Object INSTANCE_LOCK = new Object();
44    @GuardedBy("instanceLock")
45    private static Activity sInstance;
46
47    private BroadcastReceiver finishCommandReceiver = null;
48
49    @Override
50    public void onCreate(Bundle savedInstanceState) {
51        super.onCreate(savedInstanceState);
52        synchronized (INSTANCE_LOCK) {
53            sInstance = this;
54        }
55        Log.i(TAG, "onCreate called");
56
57        notifyNetworkStateObserver();
58
59        finishCommandReceiver = new BroadcastReceiver() {
60            @Override
61            public void onReceive(Context context, Intent intent) {
62                Log.i(TAG, "finish command received");
63                ConnTestActivity.this.finish();
64            }
65        };
66        registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
67    }
68
69    @Override
70    public void onResume() {
71        super.onResume();
72        Log.i(TAG, "onResume called");
73    }
74
75    @Override
76    public void onStop() {
77        Log.i(TAG, "onStop called");
78        if (finishCommandReceiver != null) {
79            unregisterReceiver(finishCommandReceiver);
80        }
81        super.onStop();
82    }
83
84    @Override
85    public void finish() {
86        synchronized (INSTANCE_LOCK) {
87            sInstance = null;
88        }
89        Log.i(TAG, "finish called");
90        super.finish();
91    }
92
93    public static void finishSelf() {
94        synchronized (INSTANCE_LOCK) {
95            if (sInstance != null) {
96                sInstance.finish();
97            }
98        }
99    }
100
101    private void notifyNetworkStateObserver() {
102        if (getIntent() == null) {
103            return;
104        }
105
106        final Bundle extras = getIntent().getExtras();
107        if (extras == null) {
108            return;
109        }
110        final INetworkStateObserver observer = INetworkStateObserver.Stub.asInterface(
111                extras.getBinder(EXTRA_NETWORK_STATE_OBSERVER));
112        if (observer != null) {
113            AsyncTask.execute(() -> {
114                try {
115                    observer.onNetworkStateChecked(checkNetworkStatus());
116                } catch (RemoteException e) {
117                    Log.e(TAG, "Error occured while notifying the observer: " + e);
118                }
119            });
120        }
121    }
122
123    /**
124     * Checks whether the network is restricted.
125     *
126     * @return null if network is not restricted, otherwise an error message.
127     */
128    private String checkNetworkStatus() {
129        final INetworkManagementService nms = INetworkManagementService.Stub.asInterface(
130                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
131        final INetworkPolicyManager npms = INetworkPolicyManager.Stub.asInterface(
132                ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
133        try {
134            final boolean restrictedByFwRules = nms.isNetworkRestricted(Process.myUid());
135            final boolean restrictedByUidRules = npms.isUidNetworkingBlocked(Process.myUid(), true);
136            if (restrictedByFwRules || restrictedByUidRules) {
137                return "Network is restricted by fwRules: " + restrictedByFwRules
138                        + " and uidRules: " + restrictedByUidRules;
139            }
140            return null;
141        } catch (RemoteException e) {
142            return "Error talking to system server: " + e;
143        }
144    }
145}