/* * Copyright (C) 2022 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.statusbar.policy; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.safetycenter.SafetyCenterManager; import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.qualifiers.Background; import java.util.ArrayList; import java.util.Objects; import javax.inject.Inject; /** * Controller which calls listeners when a PACKAGE_CHANGED broadcast is sent for the * PermissionController. These broadcasts may be because the PermissionController enabled or * disabled its TileService, and the tile should be added if the component was enabled, or removed * if disabled. */ public class SafetyController implements CallbackController { private boolean mSafetyCenterEnabled; private final Handler mBgHandler; private final ArrayList mListeners = new ArrayList<>(); private static final IntentFilter PKG_CHANGE_INTENT_FILTER; private final Context mContext; private final SafetyCenterManager mSafetyCenterManager; private final PackageManager mPackageManager; static { PKG_CHANGE_INTENT_FILTER = new IntentFilter(Intent.ACTION_PACKAGE_CHANGED); PKG_CHANGE_INTENT_FILTER.addDataScheme("package"); } @Inject public SafetyController(Context context, PackageManager pm, SafetyCenterManager scm, @Background Handler bgHandler) { mContext = context; mSafetyCenterManager = scm; mPackageManager = pm; mBgHandler = bgHandler; mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); } public boolean isSafetyCenterEnabled() { return mSafetyCenterEnabled; } /** * Adds a listener, registering the broadcast receiver if need be. Immediately calls the * provided listener on the calling thread. */ @Override public void addCallback(@NonNull Listener listener) { synchronized (mListeners) { mListeners.add(listener); if (mListeners.size() == 1) { mContext.registerReceiver(mPermControllerChangeReceiver, PKG_CHANGE_INTENT_FILTER); mBgHandler.post(() -> { mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled()); }); } else { listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled()); } } } @Override public void removeCallback(@NonNull Listener listener) { synchronized (mListeners) { mListeners.remove(listener); if (mListeners.isEmpty()) { mContext.unregisterReceiver(mPermControllerChangeReceiver); } } } private void handleSafetyCenterEnableChange() { synchronized (mListeners) { for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onSafetyCenterEnableChanged(mSafetyCenterEnabled); } } } /** * Upon receiving a package changed broadcast for the PermissionController, checks if the * safety center is enabled or disabled, and sends an update on the main thread if the state * changed. */ @VisibleForTesting final BroadcastReceiver mPermControllerChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String packageName = intent.getData() != null ? intent.getData().getSchemeSpecificPart() : null; if (!Objects.equals(packageName, mPackageManager.getPermissionControllerPackageName())) { return; } boolean wasSafetyCenterEnabled = mSafetyCenterEnabled; mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); if (wasSafetyCenterEnabled == mSafetyCenterEnabled) { return; } mBgHandler.post(() -> handleSafetyCenterEnableChange()); } }; /** * Listener for safety center enabled changes */ public interface Listener { /** * Callback to be notified when the safety center is enabled or disabled * @param isSafetyCenterEnabled If the safety center is enabled */ void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled); } }