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

Commit 448c6c68 authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge "Remove AppWidget complication support."

parents b56820d3 defb2c2f
Loading
Loading
Loading
Loading
+0 −16
Original line number Diff line number Diff line
@@ -716,22 +716,6 @@
    <!-- Flag to enable privacy dot views, it shall be true for normal case -->
    <bool name="config_enablePrivacyDot">true</bool>

    <!-- The positions widgets can be in defined as View.Gravity constants -->
    <integer-array name="config_dreamComplicationPositions">
    </integer-array>

    <!-- Widget components to show as dream complications -->
    <string-array name="config_dreamAppWidgetComplications" translatable="false">
    </string-array>

    <!-- Width percentage of dream complications -->
    <item name="config_dreamComplicationWidthPercent" translatable="false" format="float"
          type="dimen">0.33</item>

    <!-- Height percentage of dream complications -->
    <item name="config_dreamComplicationHeightPercent" translatable="false" format="float"
          type="dimen">0.25</item>

    <!-- Flag to enable dream overlay service and its registration -->
    <bool name="config_dreamOverlayServiceEnabled">false</bool>

+0 −8
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import com.android.systemui.accessibility.WindowMagnification;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.clipboardoverlay.ClipboardListener;
import com.android.systemui.dreams.DreamOverlayRegistrant;
import com.android.systemui.dreams.appwidgets.ComplicationPrimer;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
@@ -212,11 +211,4 @@ public abstract class SystemUIBinder {
    @ClassKey(DreamOverlayRegistrant.class)
    public abstract CoreStartable bindDreamOverlayRegistrant(
            DreamOverlayRegistrant dreamOverlayRegistrant);

    /** Inject into AppWidgetOverlayPrimer. */
    @Binds
    @IntoMap
    @ClassKey(ComplicationPrimer.class)
    public abstract CoreStartable bindAppWidgetOverlayPrimer(
            ComplicationPrimer complicationPrimer);
}
+0 −101
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.systemui.dreams.appwidgets;

import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;

import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;

import java.util.List;

import javax.inject.Inject;

/**
 * {@link AppWidgetProvider} is a singleton for accessing app widgets within SystemUI. This
 * consolidates resources such as the {@link AppWidgetHost} across potentially multiple
 * {@link ComplicationProvider} instances and other usages.
 */
@SysUISingleton
public class AppWidgetProvider {
    private static final String TAG = "AppWidgetProvider";
    public static final int APP_WIDGET_HOST_ID = 1025;

    private final Context mContext;
    private final AppWidgetManager mAppWidgetManager;
    private final AppWidgetHost mAppWidgetHost;
    private final Resources mResources;

    @Inject
    public AppWidgetProvider(Context context, @Main Resources resources) {
        mContext = context;
        mResources = resources;
        mAppWidgetManager = android.appwidget.AppWidgetManager.getInstance(context);
        mAppWidgetHost = new AppWidgetHost(context, APP_WIDGET_HOST_ID);
        mAppWidgetHost.startListening();
    }

    /**
     * Returns an {@link AppWidgetHostView} associated with a given {@link ComponentName}.
     * @param component The {@link ComponentName} of the target {@link AppWidgetHostView}.
     * @return The {@link AppWidgetHostView} or {@code null} on error.
     */
    public AppWidgetHostView getWidget(ComponentName component) {
        final List<AppWidgetProviderInfo> appWidgetInfos =
                mAppWidgetManager.getInstalledProviders();

        for (AppWidgetProviderInfo widgetInfo : appWidgetInfos) {
            if (widgetInfo.provider.equals(component)) {
                final int widgetId = mAppWidgetHost.allocateAppWidgetId();

                boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(widgetId,
                        widgetInfo.provider);

                if (!success) {
                    Log.e(TAG, "could not bind to app widget:" + component);
                    break;
                }

                final AppWidgetHostView appWidgetView =
                        mAppWidgetHost.createView(mContext, widgetId, widgetInfo);

                if (appWidgetView != null) {
                    // Register a layout change listener to update the widget on any sizing changes.
                    appWidgetView.addOnLayoutChangeListener(
                            (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                                final float density = mResources.getDisplayMetrics().density;
                                final int height = Math.round((bottom - top) / density);
                                final int width = Math.round((right - left) / density);
                                appWidgetView.updateAppWidgetSize(null, width, height,
                                        width, height);
                            });
                }

                return appWidgetView;
            }
        }

        return null;
    }
}
+0 −120
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.systemui.dreams.appwidgets;

import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.view.Gravity;

import androidx.constraintlayout.widget.ConstraintSet;

import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.ComplicationHostView;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.appwidgets.dagger.AppWidgetComponent;

import javax.inject.Inject;

/**
 * {@link ComplicationPrimer} reads the configured AppWidget Complications from resources on start
 * and populates them into the {@link DreamOverlayStateController}.
 */
public class ComplicationPrimer extends CoreStartable {
    private final Resources mResources;
    private final DreamOverlayStateController mDreamOverlayStateController;
    private final AppWidgetComponent.Factory mComponentFactory;

    @Inject
    public ComplicationPrimer(Context context, @Main Resources resources,
            DreamOverlayStateController overlayStateController,
            AppWidgetComponent.Factory appWidgetOverlayFactory) {
        super(context);
        mResources = resources;
        mDreamOverlayStateController = overlayStateController;
        mComponentFactory = appWidgetOverlayFactory;
    }

    @Override
    public void start() {
    }

    @Override
    protected void onBootCompleted() {
        super.onBootCompleted();
        loadDefaultWidgets();
    }

    /**
     * Generates the {@link ComplicationHostView.LayoutParams} for a given gravity. Default
     * dimension constraints are also included in the params.
     * @param gravity The gravity for the layout as defined by {@link Gravity}.
     * @param resources The resourcs from which default dimensions will be extracted from.
     * @return {@link ComplicationHostView.LayoutParams} representing the provided gravity and
     *         default parameters.
     */
    private static ComplicationHostView.LayoutParams getLayoutParams(int gravity,
            Resources resources) {
        final ComplicationHostView.LayoutParams params = new ComplicationHostView.LayoutParams(
                ComplicationHostView.LayoutParams.MATCH_CONSTRAINT,
                ComplicationHostView.LayoutParams.MATCH_CONSTRAINT);

        if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
            params.bottomToBottom = ConstraintSet.PARENT_ID;
        }

        if ((gravity & Gravity.TOP) == Gravity.TOP) {
            params.topToTop = ConstraintSet.PARENT_ID;
        }

        if ((gravity & Gravity.END) == Gravity.END) {
            params.endToEnd = ConstraintSet.PARENT_ID;
        }

        if ((gravity & Gravity.START) == Gravity.START) {
            params.startToStart = ConstraintSet.PARENT_ID;
        }

        // For now, apply the same sizing constraints on every widget.
        params.matchConstraintPercentHeight =
                resources.getFloat(R.dimen.config_dreamComplicationHeightPercent);
        params.matchConstraintPercentWidth =
                resources.getFloat(R.dimen.config_dreamComplicationWidthPercent);

        return params;
    }

    /**
     * Helper method for loading widgets based on configuration.
     */
    private void loadDefaultWidgets() {
        final int[] positions = mResources.getIntArray(R.array.config_dreamComplicationPositions);
        final String[] components =
                mResources.getStringArray(R.array.config_dreamAppWidgetComplications);

        for (int i = 0; i < Math.min(positions.length, components.length); i++) {
            final AppWidgetComponent component = mComponentFactory.build(
                    ComponentName.unflattenFromString(components[i]),
                    getLayoutParams(positions[i], mResources));

            mDreamOverlayStateController.addComplication(
                    component.getAppWidgetComplicationProvider());
        }
    }
}
+0 −83
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.systemui.dreams.appwidgets;

import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;

import com.android.systemui.dreams.ComplicationHost;
import com.android.systemui.dreams.ComplicationHostView;
import com.android.systemui.plugins.ActivityStarter;

import javax.inject.Inject;

/**
 * {@link ComplicationProvider} is an implementation of
 * {@link com.android.systemui.dreams.ComplicationProvider} for providing app widget-based
 * complications.
 */
public class ComplicationProvider implements com.android.systemui.dreams.ComplicationProvider {
    private static final String TAG = "AppWidgetCompProvider";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final ActivityStarter mActivityStarter;
    private final AppWidgetProvider mAppWidgetProvider;
    private final ComponentName mComponentName;
    private final ComplicationHostView.LayoutParams mLayoutParams;

    @Inject
    public ComplicationProvider(ActivityStarter activityStarter,
            ComponentName componentName, AppWidgetProvider widgetProvider,
            ComplicationHostView.LayoutParams layoutParams) {
        mActivityStarter = activityStarter;
        mComponentName = componentName;
        mAppWidgetProvider = widgetProvider;
        mLayoutParams = layoutParams;
    }

    @Override
    public void onCreateComplication(Context context,
            ComplicationHost.CreationCallback creationCallback,
            ComplicationHost.InteractionCallback interactionCallback) {
        final AppWidgetHostView widget = mAppWidgetProvider.getWidget(mComponentName);

        if (widget == null) {
            Log.e(TAG, "could not create widget");
            return;
        }

        widget.setInteractionHandler((view, pendingIntent, response) -> {
            if (pendingIntent.isActivity()) {
                if (DEBUG) {
                    Log.d(TAG, "launching pending intent from app widget:" + mComponentName);
                }
                interactionCallback.onExit();
                mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent,
                        null /*intentSentUiThreadCallback*/, view);
                return true;
            } else {
                return RemoteViews.startPendingIntent(view, pendingIntent,
                        response.getLaunchOptions(view));
            }
        });

        creationCallback.onCreated(widget, mLayoutParams);
    }
}
Loading