blob: bad6c4a391d6c81a1a95d54c305d14b95d0c63e2 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.feed;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.BundleUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager;
import org.chromium.chrome.browser.xsurface.ImageFetchClient;
import org.chromium.chrome.browser.xsurface.LoggingParameters;
import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache;
import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider;
import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider.VisibilityLogType;
import org.chromium.components.version_info.VersionConstants;
import org.chromium.content_public.browser.UiThreadTaskTraits;
/**
* Provides logging and context for all surfaces.
*/
@JNINamespace("feed::android")
public class FeedProcessScopeDependencyProvider implements ProcessScopeDependencyProvider {
private static final String FEED_SPLIT_NAME = "feedv2";
private Context mContext;
private ImageFetchClient mImageFetchClient;
private FeedPersistentKeyValueCache mPersistentKeyValueCache;
private LibraryResolver mLibraryResolver;
private PrivacyPreferencesManager mPrivacyPreferencesManager;
private String mApiKey;
public FeedProcessScopeDependencyProvider(
String apiKey, PrivacyPreferencesManager privacyPreferencesManager) {
mContext = createFeedContext(ContextUtils.getApplicationContext());
mImageFetchClient = new FeedImageFetchClient();
mPersistentKeyValueCache = new FeedPersistentKeyValueCache();
mPrivacyPreferencesManager = privacyPreferencesManager;
mApiKey = apiKey;
if (BundleUtils.isIsolatedSplitInstalled(mContext, FEED_SPLIT_NAME)) {
mLibraryResolver = (libName) -> {
return BundleUtils.getNativeLibraryPath(libName, FEED_SPLIT_NAME);
};
}
}
@Override
public Context getContext() {
return mContext;
}
@Override
public ImageFetchClient getImageFetchClient() {
return mImageFetchClient;
}
@Override
public PersistentKeyValueCache getPersistentKeyValueCache() {
return mPersistentKeyValueCache;
}
@Override
public void logError(String tag, String format, Object... args) {
Log.e(tag, format, args);
}
@Override
public void logWarning(String tag, String format, Object... args) {
Log.w(tag, format, args);
}
@Override
public void postTask(int taskType, Runnable task, long delayMs) {
TaskTraits traits;
switch (taskType) {
case ProcessScopeDependencyProvider.TASK_TYPE_UI_THREAD:
traits = UiThreadTaskTraits.DEFAULT;
break;
case ProcessScopeDependencyProvider.TASK_TYPE_BACKGROUND_MAY_BLOCK:
traits = TaskTraits.BEST_EFFORT_MAY_BLOCK;
break;
default:
assert false : "Invalid task type";
return;
}
PostTask.postDelayedTask(traits, task, delayMs);
}
@Override
public LibraryResolver getLibraryResolver() {
return mLibraryResolver;
}
@Override
public boolean isXsurfaceUsageAndCrashReportingEnabled() {
return ChromeFeatureList.isEnabled(ChromeFeatureList.XSURFACE_METRICS_REPORTING)
&& mPrivacyPreferencesManager.isMetricsReportingEnabled();
}
public static Context createFeedContext(Context context) {
return BundleUtils.createContextForInflation(context, FEED_SPLIT_NAME);
}
@Override
public long getReliabilityLoggingId() {
return FeedServiceBridge.getReliabilityLoggingId();
}
@Override
public String getGoogleApiKey() {
return mApiKey;
}
@Override
public String getChromeVersion() {
return VersionConstants.PRODUCT_VERSION;
}
@Override
public int getChromeChannel() {
return VersionConstants.CHANNEL;
}
@Override
public int getImageMemoryCacheSizePercentage() {
return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
ChromeFeatureList.FEED_IMAGE_MEMORY_CACHE_SIZE_PERCENTAGE,
"image_memory_cache_size_percentage",
/*default=*/100);
}
@Override
public int getBitmapPoolSizePercentage() {
return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
ChromeFeatureList.FEED_IMAGE_MEMORY_CACHE_SIZE_PERCENTAGE,
"bitmap_pool_size_percentage",
/*default=*/100);
}
@Override
public int[] getExperimentIds() {
// TODO(iwells): figure out why this is being called from another thread right after FRE
if (!ThreadUtils.runningOnUiThread()) {
return new int[0];
}
return FeedProcessScopeDependencyProviderJni.get().getExperimentIds();
}
@Override
public ProcessScopeDependencyProvider.FeatureStateProvider getFeatureStateProvider() {
return ChromeFeatureList::isEnabled;
}
/**
* Stores a view FeedAction for eventual upload. 'data' is a serialized FeedAction protobuf
* message.
*/
@Override
public void processViewAction(byte[] data, LoggingParameters loggingParameters) {
FeedProcessScopeDependencyProviderJni.get().processViewAction(
data, FeedLoggingParameters.convertToProto(loggingParameters).toByteArray());
}
@Override
public void reportOnUploadVisibilityLog(@VisibilityLogType int logType, boolean success) {
switch (logType) {
case VisibilityLogType.VIEW:
RecordHistogram.recordBooleanHistogram(
"ContentSuggestions.Feed.UploadVisibilityLog.View", success);
break;
case VisibilityLogType.CLICK:
RecordHistogram.recordBooleanHistogram(
"ContentSuggestions.Feed.UploadVisibilityLog.Click", success);
break;
case VisibilityLogType.UNSPECIFIED:
// UNSPECIFIED deliberately not reported independently, but will be
// included in the base UploadVisibilityLog histogram below.
break;
}
RecordHistogram.recordBooleanHistogram(
"ContentSuggestions.Feed.UploadVisibilityLog", success);
}
@Override
public void reportVisibilityLoggingEnabled(boolean enabled) {
RecordHistogram.recordBooleanHistogram(
"ContentSuggestions.Feed.VisibilityLoggingEnabled", enabled);
}
@VisibleForTesting
@NativeMethods
public interface Natives {
int[] getExperimentIds();
String getSessionId();
void processViewAction(byte[] actionData, byte[] loggingParameters);
}
}