1 /*
2  * Copyright (C) 2023 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 
17 package com.android.server.connectivity;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.net.NetworkCapabilities;
23 import android.text.TextUtils;
24 import android.util.AndroidRuntimeException;
25 
26 import com.android.connectivity.resources.R;
27 
28 /**
29  * Utilities to fetch keepalive configuration from resources.
30  */
31 public abstract class KeepaliveResourceUtil {
32 
33     /**
34      * Read supported keepalive count for each transport type from overlay resource.
35      *
36      * @param context The context to read resource from.
37      * @return An array of supported keepalive count for each transport type.
38      */
39     @NonNull
getSupportedKeepalives(@onNull Context context)40     public static int[] getSupportedKeepalives(@NonNull Context context) {
41         String[] res = null;
42         try {
43             final ConnectivityResources connRes = new ConnectivityResources(context);
44             res = connRes.get().getStringArray(R.array.config_networkSupportedKeepaliveCount);
45         } catch (Resources.NotFoundException unused) {
46         }
47         if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource");
48 
49         final int[] ret = new int[NetworkCapabilities.MAX_TRANSPORT + 1];
50         for (final String row : res) {
51             if (TextUtils.isEmpty(row)) {
52                 throw new KeepaliveDeviceConfigurationException("Empty string");
53             }
54             final String[] arr = row.split(",");
55             if (arr.length != 2) {
56                 throw new KeepaliveDeviceConfigurationException("Invalid parameter length");
57             }
58 
59             int transport;
60             int supported;
61             try {
62                 transport = Integer.parseInt(arr[0]);
63                 supported = Integer.parseInt(arr[1]);
64             } catch (NumberFormatException e) {
65                 throw new KeepaliveDeviceConfigurationException("Invalid number format");
66             }
67 
68             if (!NetworkCapabilities.isValidTransport(transport)) {
69                 throw new KeepaliveDeviceConfigurationException("Invalid transport " + transport);
70             }
71 
72             if (supported < 0) {
73                 throw new KeepaliveDeviceConfigurationException(
74                         "Invalid supported count " + supported + " for "
75                                 + NetworkCapabilities.transportNameOf(transport));
76             }
77             ret[transport] = supported;
78         }
79         return ret;
80     }
81 
82     /**
83      * An exception thrown when the keepalive resource configuration is invalid.
84      */
85     public static class KeepaliveDeviceConfigurationException extends AndroidRuntimeException {
KeepaliveDeviceConfigurationException(final String msg)86         public KeepaliveDeviceConfigurationException(final String msg) {
87             super(msg);
88         }
89     }
90 }
91