1/*
2 * Copyright (C) 2008 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.providers.downloads;
18
19import android.app.DownloadManager;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.ApplicationInfo;
23import android.content.pm.PackageInfo;
24import android.content.pm.PackageManager;
25import android.content.pm.PackageManager.NameNotFoundException;
26import android.net.ConnectivityManager;
27import android.net.Network;
28import android.net.NetworkCapabilities;
29import android.net.NetworkInfo;
30import android.security.NetworkSecurityPolicy;
31import android.security.net.config.ApplicationConfig;
32
33import java.security.GeneralSecurityException;
34
35import javax.net.ssl.SSLContext;
36import javax.net.ssl.TrustManager;
37
38import com.android.internal.util.ArrayUtils;
39
40class RealSystemFacade implements SystemFacade {
41    private Context mContext;
42
43    public RealSystemFacade(Context context) {
44        mContext = context;
45    }
46
47    @Override
48    public long currentTimeMillis() {
49        return System.currentTimeMillis();
50    }
51
52    @Override
53    public Network getActiveNetwork(int uid, boolean ignoreBlocked) {
54        return mContext.getSystemService(ConnectivityManager.class)
55                .getActiveNetworkForUid(uid, ignoreBlocked);
56    }
57
58    @Override
59    public NetworkInfo getNetworkInfo(Network network, int uid, boolean ignoreBlocked) {
60        return mContext.getSystemService(ConnectivityManager.class)
61                .getNetworkInfoForUid(network, uid, ignoreBlocked);
62    }
63
64    @Override
65    public boolean isNetworkMetered(Network network) {
66        return !mContext.getSystemService(ConnectivityManager.class).getNetworkCapabilities(network)
67                .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
68    }
69
70    @Override
71    public long getMaxBytesOverMobile() {
72        final Long value = DownloadManager.getMaxBytesOverMobile(mContext);
73        return (value == null) ? Long.MAX_VALUE : value;
74    }
75
76    @Override
77    public long getRecommendedMaxBytesOverMobile() {
78        final Long value = DownloadManager.getRecommendedMaxBytesOverMobile(mContext);
79        return (value == null) ? Long.MAX_VALUE : value;
80    }
81
82    @Override
83    public void sendBroadcast(Intent intent) {
84        mContext.sendBroadcast(intent);
85    }
86
87    @Override
88    public boolean userOwnsPackage(int uid, String packageName) throws NameNotFoundException {
89        return mContext.getPackageManager().getApplicationInfo(packageName, 0).uid == uid;
90    }
91
92    @Override
93    public boolean isCleartextTrafficPermitted(int uid) {
94        PackageManager packageManager = mContext.getPackageManager();
95        String[] packageNames = packageManager.getPackagesForUid(uid);
96        if (ArrayUtils.isEmpty(packageNames)) {
97            // Unknown UID -- fail safe: cleartext traffic not permitted
98            return false;
99        }
100
101        // Cleartext traffic is permitted from the UID if it's permitted for any of the packages
102        // belonging to that UID.
103        for (String packageName : packageNames) {
104            if (isCleartextTrafficPermitted(packageName)) {
105                return true;
106            }
107        }
108        return false;
109    }
110
111    @Override
112    public SSLContext getSSLContextForPackage(Context context, String packageName)
113            throws GeneralSecurityException {
114        ApplicationConfig appConfig;
115        try {
116            appConfig = NetworkSecurityPolicy.getApplicationConfigForPackage(context, packageName);
117        } catch (NameNotFoundException e) {
118            // Unknown package -- fallback to the default SSLContext
119            return SSLContext.getDefault();
120        }
121        SSLContext ctx = SSLContext.getInstance("TLS");
122        ctx.init(null, new TrustManager[] {appConfig.getTrustManager()}, null);
123        return ctx;
124    }
125
126    /**
127     * Returns whether cleartext network traffic (HTTP) is permitted for the provided package.
128     */
129    private boolean isCleartextTrafficPermitted(String packageName) {
130        PackageManager packageManager = mContext.getPackageManager();
131        PackageInfo packageInfo;
132        try {
133            packageInfo = packageManager.getPackageInfo(packageName, 0);
134        } catch (NameNotFoundException e) {
135            // Unknown package -- fail safe: cleartext traffic not permitted
136            return false;
137        }
138        ApplicationInfo applicationInfo = packageInfo.applicationInfo;
139        if (applicationInfo == null) {
140            // No app info -- fail safe: cleartext traffic not permitted
141            return false;
142        }
143        return (applicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0;
144    }
145}
146