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

Commit cfc685da authored by Sihua Ma's avatar Sihua Ma Committed by Android (Google) Code Review
Browse files

Merge "Combining widget broadcasts"

parents fc93defc 1ae08fe7
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
@@ -567,6 +567,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;
@@ -253,11 +254,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);
@@ -273,6 +276,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");
        }
@@ -1092,15 +1097,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));
@@ -2332,6 +2337,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);
@@ -2823,7 +2844,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,
@@ -2832,7 +2852,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