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

Commit 373b3e5a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Combining widget broadcasts" into tm-qpr-dev am: e6e061e5

parents 175ef1cf e6e061e5
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -42,12 +42,15 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.RemoteViews;

import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * Updates AppWidget state; gets information about installed AppWidget providers and other
@@ -63,6 +66,7 @@ import java.util.List;
@RequiresFeature(PackageManager.FEATURE_APP_WIDGETS)
public class AppWidgetManager {


    /**
     * Activity action to launch from your {@link AppWidgetHost} activity when you want to
     * pick an AppWidget to display.  The AppWidget picker activity will be launched.
@@ -331,6 +335,17 @@ public class AppWidgetManager {
    @BroadcastBehavior(explicitOnly = true)
    public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";

    /**
     * A combination broadcast of APPWIDGET_ENABLED and APPWIDGET_UPDATE.
     * Sent during boot time and when the host is binding the widget for the very first time
     *
     * @hide
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    @BroadcastBehavior(explicitOnly = true)
    public static final String ACTION_APPWIDGET_ENABLE_AND_UPDATE = "android.appwidget.action"
            + ".APPWIDGET_ENABLE_AND_UPDATE";

    /**
     * Sent when the custom extras for an AppWidget change.
     *
@@ -456,6 +471,8 @@ public class AppWidgetManager {
    public static final String ACTION_APPWIDGET_HOST_RESTORED
            = "android.appwidget.action.APPWIDGET_HOST_RESTORED";

    private static final String TAG = "AppWidgetManager";

    /**
     * An intent extra that contains multiple appWidgetIds.  These are id values as
     * they were provided to the application during a recent restore from backup.  It is
@@ -511,6 +528,26 @@ public class AppWidgetManager {
        mPackageName = context.getOpPackageName();
        mService = service;
        mDisplayMetrics = context.getResources().getDisplayMetrics();
        if (mService == null) {
            return;
        }
        BackgroundThread.getExecutor().execute(() -> {
            try {
                mService.notifyProviderInheritance(getInstalledProvidersForPackage(mPackageName,
                        null)
                        .stream().filter(Objects::nonNull)
                        .map(info -> info.provider).filter(p -> {
                            try {
                                Class clazz = Class.forName(p.getClassName());
                                return AppWidgetProvider.class.isAssignableFrom(clazz);
                            } catch (Exception e) {
                                return false;
                            }
                        }).toArray(ComponentName[]::new));
            } catch (Exception e) {
                Log.e(TAG, "Nofity service of inheritance info", e);
            }
        });
    }

    /**
+6 −1
Original line number Diff line number Diff line
@@ -58,7 +58,12 @@ public class AppWidgetProvider extends BroadcastReceiver {
        // Protect against rogue update broadcasts (not really a security issue,
        // just filter bad broacasts out so subclasses are less likely to crash).
        String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
        if (AppWidgetManager.ACTION_APPWIDGET_ENABLE_AND_UPDATE.equals(action)) {
            this.onReceive(context, new Intent(intent)
                    .setAction(AppWidgetManager.ACTION_APPWIDGET_ENABLED));
            this.onReceive(context, new Intent(intent)
                    .setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE));
        } else if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
+5 −0
Original line number Diff line number Diff line
@@ -578,6 +578,11 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String CLIPBOARD_OVERLAY_SHOW_ACTIONS = "clipboard_overlay_show_actions";

    /**
     * (boolean) Whether to combine the broadcasts APPWIDGET_ENABLED and APPWIDGET_UPDATE
     */
    public static final String COMBINED_BROADCAST_ENABLED = "combined_broadcast_enabled";

    private SystemUiDeviceConfigFlags() {
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@
    <protected-broadcast android:name="android.appwidget.action.APPWIDGET_ENABLED" />
    <protected-broadcast android:name="android.appwidget.action.APPWIDGET_HOST_RESTORED" />
    <protected-broadcast android:name="android.appwidget.action.APPWIDGET_RESTORED" />
    <protected-broadcast android:name="android.appwidget.action.APPWIDGET_ENABLE_AND_UPDATE" />

    <protected-broadcast android:name="android.os.action.SETTING_RESTORED" />

+30 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -254,11 +255,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    private boolean mSafeMode;
    private int mMaxWidgetBitmapMemory;
    private boolean mIsProviderInfoPersisted;
    private boolean mIsCombinedBroadcastEnabled;

    AppWidgetServiceImpl(Context context) {
        mContext = context;
    }

    @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG)
    public void onStart() {
        mPackageManager = AppGlobals.getPackageManager();
        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -277,6 +280,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        mIsProviderInfoPersisted = !ActivityManager.isLowRamDeviceStatic()
                && DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.PERSISTS_WIDGET_PROVIDER_INFO, true);
        mIsCombinedBroadcastEnabled = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
            SystemUiDeviceConfigFlags.COMBINED_BROADCAST_ENABLED, true);
        if (DEBUG_PROVIDER_INFO_CACHE && !mIsProviderInfoPersisted) {
            Slog.d(TAG, "App widget provider info will not be persisted on this device");
        }
@@ -1123,15 +1128,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku

            final int widgetCount = provider.widgets.size();
            if (widgetCount == 1) {
                // Tell the provider that it's ready.
                sendEnableIntentLocked(provider);
            }

            // Send an update now -- We need this update now, and just for this appWidgetId.
            // It's less critical when the next one happens, so when we schedule the next one,
            // we add updatePeriodMillis to its start time. That time will have some slop,
            // but that's okay.
                // If we are binding the very first widget from a provider, we will send
                // a combined broadcast or 2 separate broadcasts to tell the provider that
                // it's ready, and we need them to provide the update now.
                sendEnableAndUpdateIntentLocked(provider, new int[]{appWidgetId});
            } else {
                // For any widget other then the first one, we just send update intent
                // as we normally would.
                sendUpdateIntentLocked(provider, new int[]{appWidgetId});
            }

            // Schedule the future updates.
            registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets));
@@ -2361,6 +2366,22 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        cancelBroadcastsLocked(provider);
    }

    private void sendEnableAndUpdateIntentLocked(@NonNull Provider p, int[] appWidgetIds) {
        final boolean canSendCombinedBroadcast = mIsCombinedBroadcastEnabled && p.info != null
                && p.info.isExtendedFromAppWidgetProvider;
        if (!canSendCombinedBroadcast) {
            // If this function is called by mistake, send two separate broadcasts instead
            sendEnableIntentLocked(p);
            sendUpdateIntentLocked(p, appWidgetIds);
            return;
        }

        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLE_AND_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
        intent.setComponent(p.id.componentName);
        sendBroadcastAsUser(intent, p.id.getProfile());
    }

    private void sendEnableIntentLocked(Provider p) {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED);
        intent.setComponent(p.id.componentName);
@@ -2852,7 +2873,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                if (provider.widgets.size() > 0) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "appwidget init " + provider.id.componentName.getPackageName());
                    sendEnableIntentLocked(provider);
                    provider.widgets.forEach(widget -> {
                        widget.trackingUpdate = true;
                        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
@@ -2861,7 +2881,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                        Log.i(TAG, "Widget update scheduled on unlock " + widget.toString());
                    });
                    int[] appWidgetIds = getWidgetIds(provider.widgets);
                    sendUpdateIntentLocked(provider, appWidgetIds);
                    sendEnableAndUpdateIntentLocked(provider, appWidgetIds);
                    registerForBroadcastsLocked(provider, appWidgetIds);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
Loading