| /* |
| * Copyright (C) 2020 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.server.pm; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| |
| import com.android.server.IntentResolver; |
| import com.android.server.utils.Snappable; |
| import com.android.server.utils.Watchable; |
| import com.android.server.utils.WatchableImpl; |
| import com.android.server.utils.Watcher; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| /** |
| * A watched {@link IntentResolver}. The parameters are inherited from the superclass. |
| * @param <F> The filter type |
| * @param <R> The resolver type. |
| * {@hide} |
| */ |
| public abstract class WatchedIntentResolver<F extends WatchedIntentFilter, |
| R extends WatchedIntentFilter> |
| extends IntentResolver<F, R> |
| implements Watchable, Snappable { |
| |
| /** |
| * Watchable machinery |
| */ |
| private final Watchable mWatchable = new WatchableImpl(); |
| |
| /** |
| * Register an observer to receive change notifications. |
| * @param observer The observer to register. |
| */ |
| @Override |
| public void registerObserver(@NonNull Watcher observer) { |
| mWatchable.registerObserver(observer); |
| } |
| |
| /** |
| * Unregister the observer, which will no longer receive change notifications. |
| * @param observer The observer to unregister. |
| */ |
| @Override |
| public void unregisterObserver(@NonNull Watcher observer) { |
| mWatchable.unregisterObserver(observer); |
| } |
| |
| /** |
| * Return true if the {@link Watcher) is a registered observer. |
| * @param observer A {@link Watcher} that might be registered |
| * @return true if the observer is registered with this {@link Watchable}. |
| */ |
| @Override |
| public boolean isRegisteredObserver(@NonNull Watcher observer) { |
| return mWatchable.isRegisteredObserver(observer); |
| } |
| |
| /** |
| * Notify listeners that the object has changd. The argument is a hint as to the |
| * source of the change. |
| * @param what The attribute or sub-object that changed, if not null. |
| */ |
| @Override |
| public void dispatchChange(@Nullable Watchable what) { |
| mWatchable.dispatchChange(what); |
| } |
| |
| private final Watcher mWatcher = new Watcher() { |
| @Override |
| public void onChange(@Nullable Watchable what) { |
| dispatchChange(what); |
| } |
| }; |
| |
| /** |
| * Notify listeners that this object has changed. |
| */ |
| protected void onChanged() { |
| dispatchChange(this); |
| } |
| |
| @Override |
| public void addFilter(F f) { |
| super.addFilter(f); |
| f.registerObserver(mWatcher); |
| onChanged(); |
| } |
| |
| @Override |
| public void removeFilter(F f) { |
| f.unregisterObserver(mWatcher); |
| super.removeFilter(f); |
| onChanged(); |
| } |
| |
| @Override |
| protected void removeFilterInternal(F f) { |
| f.unregisterObserver(mWatcher); |
| super.removeFilterInternal(f); |
| onChanged(); |
| } |
| |
| // Sorts a List of IntentFilter objects into descending priority order. |
| @SuppressWarnings("rawtypes") |
| private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter = |
| new Comparator<>() { |
| public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) { |
| final int q1 = o1.getPriority(); |
| final int q2 = o2.getPriority(); |
| return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); |
| } |
| }; |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| protected void sortResults(List<R> results) { |
| Collections.sort(results, sResolvePrioritySorter); |
| } |
| |
| /** |
| * @see IntentResolver#findFilters(IntentFilter) |
| */ |
| public ArrayList<F> findFilters(WatchedIntentFilter matching) { |
| return super.findFilters(matching.getIntentFilter()); |
| } |
| |
| // Make <this> a copy of <orig>. The presumption is that <this> is empty but all |
| // arrays are cleared out explicitly, just to be sure. |
| protected void copyFrom(WatchedIntentResolver orig) { |
| super.copyFrom(orig); |
| } |
| } |