• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.net.impl;
6 
7 import android.content.ComponentName;
8 import android.content.Context;
9 import android.content.pm.PackageManager;
10 import android.content.pm.ServiceInfo;
11 import android.os.Bundle;
12 
13 import androidx.annotation.VisibleForTesting;
14 
15 import org.chromium.net.impl.CronetLogger.CronetSource;
16 
17 /**
18  * Utilities for working with Cronet Android manifest flags.
19  *
20  * Cronet manifest flags must be defined within a service definition named after {@link
21  * #META_DATA_HOLDER_SERVICE_NAME} (the reason this is not defined at the application level is to
22  * avoid scalability issues with PackageManager queries). For example, to enable telemetry, add the
23  * following to {@code AndroidManifest.xml}:
24  *
25  * <pre>{@code
26  * <manifest ...>
27  *   ...
28  *   <application ...>
29  *     ...
30  *     <service android:name="android.net.http.MetaDataHolder"
31  *              android:enabled="false" android:exported="false">
32  *       <meta-data android:name="android.net.http.EnableTelemetry"
33  *                  android:value="true" />
34  *     </service>
35  *   </application>
36  * </manifest>
37  * }</pre>
38  */
39 @VisibleForTesting
40 public final class CronetManifest {
CronetManifest()41     private CronetManifest() {}
42 
43     @VisibleForTesting
44     static final String META_DATA_HOLDER_SERVICE_NAME = "android.net.http.MetaDataHolder";
45 
46     @VisibleForTesting
47     static final String ENABLE_TELEMETRY_META_DATA_KEY = "android.net.http.EnableTelemetry";
48 
49     // DO NOT ENABLE this manifest flag in production apps. The code gated behind this flag is not
50     // ready yet.
51     // TODO: remove the "Experimental" prefix once the code for reading HTTP flags is ready.
52     @VisibleForTesting
53     public static final String READ_HTTP_FLAGS_META_DATA_KEY =
54             "android.net.http.EXPERIMENTAL_ReadHttpFlags";
55 
56     /**
57      * @return True if telemetry should be enabled, based on the {@link
58      * #ENABLE_TELEMETRY_META_DATA_KEY} meta-data entry in the Android manifest.
59      */
isAppOptedInForTelemetry(Context context, CronetSource source)60     public static boolean isAppOptedInForTelemetry(Context context, CronetSource source) {
61         boolean telemetryIsDefaultEnabled =
62                 source == CronetSource.CRONET_SOURCE_PLATFORM
63                         || source == CronetSource.CRONET_SOURCE_PLAY_SERVICES;
64         return getMetaData(context)
65                 .getBoolean(
66                         ENABLE_TELEMETRY_META_DATA_KEY, /* default= */ telemetryIsDefaultEnabled);
67     }
68 
69     /**
70      * @return True if HTTP flags (typically used for experiments) should be enabled, based on the
71      * {@link #READ_HTTP_FLAGS_META_DATA_KEY} meta-data entry in the Android manifest.
72      * @see HttpFlagsLoader
73      */
shouldReadHttpFlags(Context context)74     public static boolean shouldReadHttpFlags(Context context) {
75         // TODO: switch the default to true once we confirm the HTTP flags system is working as
76         // intended.
77         return getMetaData(context).getBoolean(READ_HTTP_FLAGS_META_DATA_KEY, /* default= */ false);
78     }
79 
80     /**
81      * @return The meta-data contained within the Cronet meta-data holder service definition in the
82      * Android manifest, or an empty Bundle if there is no such definition. Never returns null.
83      */
getMetaData(Context context)84     private static Bundle getMetaData(Context context) {
85         ServiceInfo serviceInfo;
86         try {
87             serviceInfo =
88                     context.getPackageManager()
89                             .getServiceInfo(
90                                     new ComponentName(context, META_DATA_HOLDER_SERVICE_NAME),
91                                     PackageManager.GET_META_DATA
92                                             | PackageManager.MATCH_DISABLED_COMPONENTS
93                                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
94                                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
95         } catch (PackageManager.NameNotFoundException e) {
96             serviceInfo = null;
97         }
98         return serviceInfo != null ? serviceInfo.metaData : new Bundle();
99     }
100 }
101