Files
app_Settings/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
Jason Chiu ad9a214fff Revert "Revert "Fix SecurityException while accessing Slice Uris""
This reverts commit 52ac47d9c8.

Reason for revert: This CL is what we wanted to merge in RVC and has already got Code-Review +2, Owner-Approval, and DrNo-Review from other folks regardless of the accident.

Bug: 159195420
Change-Id: I6c646269cd3e13e015dcc06418e21db66372e680
2020-06-20 07:04:52 +00:00

131 lines
4.3 KiB
Java

/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.homepage.contextualcards;
import static android.app.slice.Slice.HINT_ERROR;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
import androidx.slice.SliceViewManager;
import androidx.slice.core.SliceAction;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.List;
import java.util.concurrent.Callable;
public class EligibleCardChecker implements Callable<ContextualCard> {
private static final String TAG = "EligibleCardChecker";
private final Context mContext;
@VisibleForTesting
ContextualCard mCard;
EligibleCardChecker(Context context, ContextualCard card) {
mContext = context;
mCard = card;
}
@Override
public ContextualCard call() {
final long startTime = System.currentTimeMillis();
final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
ContextualCard result;
if (isCardEligibleToDisplay(mCard)) {
metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
SettingsEnums.SETTINGS_HOMEPAGE,
mCard.getTextSliceUri() /* key */, 1 /* true */);
result = mCard;
} else {
metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
SettingsEnums.SETTINGS_HOMEPAGE,
mCard.getTextSliceUri() /* key */, 0 /* false */);
result = null;
}
// Log individual card loading time
metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD,
SettingsEnums.SETTINGS_HOMEPAGE,
mCard.getTextSliceUri() /* key */,
(int) (System.currentTimeMillis() - startTime) /* value */);
return result;
}
@VisibleForTesting
boolean isCardEligibleToDisplay(ContextualCard card) {
if (card.getRankingScore() < 0) {
return false;
}
final Uri uri = card.getSliceUri();
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
return false;
}
final Slice slice = bindSlice(uri);
if (slice == null || slice.hasHint(HINT_ERROR)) {
Log.w(TAG, "Failed to bind slice, not eligible for display " + uri);
return false;
}
mCard = card.mutate().setSlice(slice).build();
if (isSliceToggleable(slice)) {
mCard = card.mutate().setHasInlineAction(true).build();
}
return true;
}
@VisibleForTesting
Slice bindSlice(Uri uri) {
final SliceViewManager manager = SliceViewManager.getInstance(mContext);
final SliceViewManager.SliceCallback callback = slice -> { };
// Register a trivial callback to pin the slice
manager.registerSliceCallback(uri, callback);
final Slice slice = manager.bindSlice(uri);
manager.unregisterSliceCallback(uri, callback);
return slice;
}
@VisibleForTesting
boolean isSliceToggleable(Slice slice) {
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
final List<SliceAction> toggles = metadata.getToggles();
return !toggles.isEmpty();
}
}