CommunalSourcePackageObserver Introduction.
This changelist introduces the CommunalSourcePackageObserver, which handles notifying when the package is updated or added. Bug: 202784947 Test: atest CommunalSourcePackageObserverTest Change-Id: I945717af0dec15532bdd0a110d5f92859bbdf118
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.communal;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PatternMatcher;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* {@link PackageObserver} allows for monitoring the system for changes relating to a particular
|
||||
* package. This can be used by {@link CommunalSource} clients to detect when a related package
|
||||
* has changed and reloading is necessary.
|
||||
*/
|
||||
public class PackageObserver implements CommunalSource.Observer {
|
||||
private static final String TAG = "PackageObserver";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList();
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "package added receiver - onReceive");
|
||||
}
|
||||
|
||||
final Iterator<WeakReference<Callback>> iter = mCallbacks.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Callback callback = iter.next().get();
|
||||
if (callback != null) {
|
||||
callback.onSourceChanged();
|
||||
} else {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final String mPackageName;
|
||||
private final Context mContext;
|
||||
|
||||
public PackageObserver(Context context, String packageName) {
|
||||
mContext = context;
|
||||
mPackageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCallback(Callback callback) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addCallback:" + callback);
|
||||
}
|
||||
mCallbacks.add(new WeakReference<>(callback));
|
||||
|
||||
// Only register for listening to package additions on first callback.
|
||||
if (mCallbacks.size() > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addDataScheme("package");
|
||||
filter.addDataSchemeSpecificPart(mPackageName, PatternMatcher.PATTERN_LITERAL);
|
||||
// Note that we directly register the receiver here as data schemes are not supported by
|
||||
// BroadcastDispatcher.
|
||||
mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCallback(Callback callback) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "removeCallback:" + callback);
|
||||
}
|
||||
final boolean removed = mCallbacks.removeIf(el -> el.get() == callback);
|
||||
|
||||
if (removed && mCallbacks.isEmpty()) {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,26 @@
|
||||
|
||||
package com.android.systemui.communal.dagger;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.communal.CommunalSource;
|
||||
import com.android.systemui.communal.PackageObserver;
|
||||
import com.android.systemui.communal.conditions.CommunalCondition;
|
||||
import com.android.systemui.communal.conditions.CommunalSettingCondition;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.idle.AmbientLightModeMonitor;
|
||||
import com.android.systemui.idle.LightSensorEventsDebounceAlgorithm;
|
||||
import com.android.systemui.idle.dagger.IdleViewComponent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Named;
|
||||
@@ -56,6 +64,20 @@ public interface CommunalModule {
|
||||
return view;
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
static Optional<CommunalSource.Observer> provideCommunalSourcePackageObserver(
|
||||
Context context, @Main Resources resources) {
|
||||
final String componentName = resources.getString(R.string.config_communalSourceComponent);
|
||||
|
||||
if (TextUtils.isEmpty(componentName)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new PackageObserver(context,
|
||||
ComponentName.unflattenFromString(componentName).getPackageName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides LightSensorEventsDebounceAlgorithm as an instance to DebounceAlgorithm interface.
|
||||
* @param algorithm the instance of algorithm that is bound to the interface.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.communal;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class PackageObserverTest extends SysuiTestCase {
|
||||
private static final String PACKAGE_NAME = "com.foo.bar";
|
||||
|
||||
@Mock
|
||||
Context mContext;
|
||||
|
||||
@Mock
|
||||
CommunalSource.Observer.Callback mCallback;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChange() {
|
||||
final PackageObserver observer = new PackageObserver(mContext, PACKAGE_NAME);
|
||||
final ArgumentCaptor<BroadcastReceiver> receiverCapture =
|
||||
ArgumentCaptor.forClass(BroadcastReceiver.class);
|
||||
|
||||
observer.addCallback(mCallback);
|
||||
|
||||
// Verify broadcast receiver registered.
|
||||
verify(mContext).registerReceiver(receiverCapture.capture(), any(), anyInt());
|
||||
|
||||
// Simulate package change.
|
||||
receiverCapture.getValue().onReceive(mContext, new Intent());
|
||||
|
||||
// Check that callback was informed.
|
||||
verify(mCallback).onSourceChanged();
|
||||
|
||||
observer.removeCallback(mCallback);
|
||||
|
||||
// Make sure receiver is unregistered on last callback removal
|
||||
verify(mContext).unregisterReceiver(receiverCapture.getValue());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user