blob: ae22d0a30421812374e13e9ed3bbeb2cb6917bba [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.net.impl;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import androidx.annotation.VisibleForTesting;
import org.chromium.net.impl.CronetLogger.CronetSource;
/**
* Utilities for working with Cronet Android manifest flags.
*
* Cronet manifest flags must be defined within a service definition named after {@link
* #META_DATA_HOLDER_SERVICE_NAME} (the reason this is not defined at the application level is to
* avoid scalability issues with PackageManager queries). For example, to enable telemetry, add the
* following to {@code AndroidManifest.xml}:
*
* <pre>{@code
* <manifest ...>
* ...
* <application ...>
* ...
* <service android:name="android.net.http.MetaDataHolder"
* android:enabled="false" android:exported="false">
* <meta-data android:name="android.net.http.EnableTelemetry"
* android:value="true" />
* </service>
* </application>
* </manifest>
* }</pre>
*/
@VisibleForTesting
public final class CronetManifest {
private CronetManifest() {}
@VisibleForTesting
static final String META_DATA_HOLDER_SERVICE_NAME = "android.net.http.MetaDataHolder";
@VisibleForTesting
static final String ENABLE_TELEMETRY_META_DATA_KEY = "android.net.http.EnableTelemetry";
// DO NOT ENABLE this manifest flag in production apps. The code gated behind this flag is not
// ready yet.
// TODO: remove the "Experimental" prefix once the code for reading HTTP flags is ready.
@VisibleForTesting
public static final String READ_HTTP_FLAGS_META_DATA_KEY =
"android.net.http.EXPERIMENTAL_ReadHttpFlags";
/**
* @return True if telemetry should be enabled, based on the {@link
* #ENABLE_TELEMETRY_META_DATA_KEY} meta-data entry in the Android manifest.
*/
public static boolean isAppOptedInForTelemetry(Context context, CronetSource source) {
boolean telemetryIsDefaultEnabled =
source == CronetSource.CRONET_SOURCE_PLATFORM
|| source == CronetSource.CRONET_SOURCE_PLAY_SERVICES;
return getMetaData(context)
.getBoolean(
ENABLE_TELEMETRY_META_DATA_KEY, /* default= */ telemetryIsDefaultEnabled);
}
/**
* @return True if HTTP flags (typically used for experiments) should be enabled, based on the
* {@link #READ_HTTP_FLAGS_META_DATA_KEY} meta-data entry in the Android manifest.
* @see HttpFlagsLoader
*/
public static boolean shouldReadHttpFlags(Context context) {
// TODO: switch the default to true once we confirm the HTTP flags system is working as
// intended.
return getMetaData(context).getBoolean(READ_HTTP_FLAGS_META_DATA_KEY, /* default= */ false);
}
/**
* @return The meta-data contained within the Cronet meta-data holder service definition in the
* Android manifest, or an empty Bundle if there is no such definition. Never returns null.
*/
private static Bundle getMetaData(Context context) {
ServiceInfo serviceInfo;
try {
serviceInfo =
context.getPackageManager()
.getServiceInfo(
new ComponentName(context, META_DATA_HOLDER_SERVICE_NAME),
PackageManager.GET_META_DATA
| PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
} catch (PackageManager.NameNotFoundException e) {
serviceInfo = null;
}
return serviceInfo != null ? serviceInfo.metaData : new Bundle();
}
}