Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 632da358 authored by Tony Huang's avatar Tony Huang Committed by android-build-merger
Browse files

Overlay manifest setting by package manager am: c39b0b23

am: 0a40cb0b

Change-Id: Ieff671aa2270a8d21e707c6f4c5ed54f952147a8
parents 42278d51 0a40cb0b
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@
            </intent-filter>
        </activity>

        <activity-alias android:name="ViewDownloadsActivity"
        <activity-alias android:name=".ViewDownloadsActivity"
                        android:targetActivity=".files.FilesActivity"
                        android:enabled="@bool/handle_view_downloads_intent">
            <intent-filter>
@@ -169,6 +169,12 @@
            </intent-filter>
        </receiver>

        <receiver android:name=".PreBootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PRE_BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <!-- Run FileOperationService in a separate process so that we can use FileLock class to
            wait until jumbo clip is done writing to disk before reading it. See ClipStorage for
            details. -->
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
            <item type="bool" name="config_button_all_caps"/>
            <item type="bool" name="config_default_show_device_root"/>
            <item type="bool" name="feature_default_root_in_browse"/>
            <item type="bool" name="handle_view_downloads_intent"/>
            <item type="bool" name="is_launcher_enabled"/>
            <item type="bool" name="show_search_bar"/>
            <!-- END BOOLEAN CONFIG -->
+104 −0
Original line number Diff line number Diff line
/*
 * 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.documentsui;

import static com.android.documentsui.base.SharedMinimal.DEBUG;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.om.OverlayInfo;
import android.content.om.OverlayManager;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.util.Log;

import com.android.documentsui.theme.ThemeOverlayManager;

/**
 * A receiver listening action.PRE_BOOT_COMPLETED event for setting component enable or disable.
 * Since there's limitation of overlay AndroidManifest.xml attrs at boot stage.
 * The workaround to retrieve config from DocumentsUI RRO package at boot time in Q.
 */
public class PreBootReceiver extends BroadcastReceiver {

    private static final String TAG = "PreBootReceiver";
    private static final String CONFIG_IS_LAUNCHER_ENABLED = "is_launcher_enabled";
    private static final String CONFIG_HANDLE_VIEW_DOWNLOADS = "handle_view_downloads_intent";
    private static final String LAUNCHER_TARGET_CLASS = "com.android.documentsui.LauncherActivity";
    private static final String DOWNLOADS_TARGET_CLASS =
            "com.android.documentsui.ViewDownloadsActivity";

    @Override
    public void onReceive(Context context, Intent intent) {
        final PackageManager pm = context.getPackageManager();
        if (pm == null) {
            Log.w(TAG, "Can't obtain PackageManager from System Service!");
            return;
        }

        final OverlayManager om = context.getSystemService(OverlayManager.class);
        if (om == null) {
            Log.w(TAG, "Can't obtain OverlayManager from System Service!");
            return;
        }

        final OverlayInfo info = new ThemeOverlayManager(om,
                context.getPackageName()).getValidOverlay(pm);

        if (info == null) {
            Log.w(TAG, "Can't get valid overlay info");
            return;
        }

        final String overlayPkg = info.getPackageName();
        final String packageName = context.getPackageName();

        Resources overlayRes;
        try {
            overlayRes = pm.getResourcesForApplication(overlayPkg);
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Failed while parse package res.");
            overlayRes = null;
        }
        if (overlayRes == null) {
            return;
        }

        setComponentEnabledByConfigResources(pm, packageName, LAUNCHER_TARGET_CLASS,
                overlayPkg, overlayRes, CONFIG_IS_LAUNCHER_ENABLED);
        setComponentEnabledByConfigResources(pm, packageName, DOWNLOADS_TARGET_CLASS,
                overlayPkg, overlayRes, CONFIG_HANDLE_VIEW_DOWNLOADS);
    }

    private static void setComponentEnabledByConfigResources(PackageManager pm, String packageName,
            String className, String overlayPkg, Resources overlayRes, String config) {
        int resId = overlayRes.getIdentifier(config, "bool", overlayPkg);
        if (resId != 0) {
            final ComponentName component = new ComponentName(packageName, className);
            final boolean value = overlayRes.getBoolean(resId);
            if (DEBUG) {
                Log.i(TAG, "Overlay package:" + overlayPkg + ", customize " + config + ":" + value);
            }
            pm.setComponentEnabledSetting(component, value
                            ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
        }
    }
}
+32 −3
Original line number Diff line number Diff line
@@ -19,13 +19,15 @@ package com.android.documentsui.theme;
import android.content.Context;
import android.content.om.OverlayInfo;
import android.content.om.OverlayManager;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.util.Consumer;

@@ -73,6 +75,34 @@ public class ThemeOverlayManager {
        return mOverlayManager.getOverlayInfosForTarget(mTargetPackageId, mUserHandle);
    }

    /**
     * Return the OverlayInfo which is provided by the docsUI overlay package located product,
     * system or vendor. We assume there should only one docsUI overlay package because priority
     * not work for non-static overlay, so vendor should put only one docsUI overlay package.
     *
     * @param pm the PackageManager
     */
    @Nullable
    public OverlayInfo getValidOverlay(@NonNull PackageManager pm) {
        for (OverlayInfo info : getOverlayInfo()) {
            try {
                final ApplicationInfo ai = pm.getApplicationInfo(info.getPackageName(), 0);
                // Since isProduct(), isVendor() and isSystemApp() functions in ApplicationInfo are
                // hidden. The best way to avoid unknown sideload APKs is filter path by string
                // comparison.
                final String sourceDir = ai.sourceDir;
                if (sourceDir.startsWith(Environment.getProductDirectory().getAbsolutePath())
                        || sourceDir.startsWith(Environment.getVendorDirectory().getAbsolutePath())
                        || sourceDir.startsWith(Environment.getRootDirectory().getAbsolutePath())) {
                    return info;
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.w(TAG, "Can't get ApplicationInfo of overlay package " + info.getPackageName());
            }
        }
        return null;
    }

    private void setEnabled(boolean enabled, Consumer<Boolean> callback) {
        new AsyncTask<Void, Void, Boolean>() {
            @Override
@@ -94,8 +124,7 @@ public class ThemeOverlayManager {
        boolean bSuccess = true;
        for (OverlayInfo info : infos) {
            try {
                if (info != null && !TextUtils.isEmpty(info.getPackageName())
                        && info.isEnabled() != enabled) {
                if (info.isEnabled() != enabled) {
                    mOverlayManager.setEnabled(info.getPackageName(), enabled, mUserHandle);
                } else {
                    Log.w(TAG, "Skip enabled overlay package:" + info.getPackageName()