1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 import com.android.server.IntentResolver;
23 import com.android.server.utils.Snappable;
24 import com.android.server.utils.Watchable;
25 import com.android.server.utils.WatchableImpl;
26 import com.android.server.utils.Watcher;
27 
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.List;
32 
33 /**
34  * A watched {@link IntentResolver}.  The parameters are inherited from the superclass.
35  * @param <F> The filter type
36  * @param <R> The resolver type.
37  * {@hide}
38  */
39 public abstract class WatchedIntentResolver<F extends WatchedIntentFilter,
40                                             R extends WatchedIntentFilter>
41         extends IntentResolver<F, R>
42         implements Watchable, Snappable {
43 
44     /**
45      * Watchable machinery
46      */
47     private final Watchable mWatchable = new WatchableImpl();
48 
49     /**
50      * Register an observer to receive change notifications.
51      * @param observer The observer to register.
52      */
53     @Override
registerObserver(@onNull Watcher observer)54     public void registerObserver(@NonNull Watcher observer) {
55         mWatchable.registerObserver(observer);
56     }
57 
58     /**
59      * Unregister the observer, which will no longer receive change notifications.
60      * @param observer The observer to unregister.
61      */
62     @Override
unregisterObserver(@onNull Watcher observer)63     public void unregisterObserver(@NonNull Watcher observer) {
64         mWatchable.unregisterObserver(observer);
65     }
66 
67     /**
68      * Return true if the {@link Watcher) is a registered observer.
69      * @param observer A {@link Watcher} that might be registered
70      * @return true if the observer is registered with this {@link Watchable}.
71      */
72     @Override
isRegisteredObserver(@onNull Watcher observer)73     public boolean isRegisteredObserver(@NonNull Watcher observer) {
74         return mWatchable.isRegisteredObserver(observer);
75     }
76 
77     /**
78      * Notify listeners that the object has changd.  The argument is a hint as to the
79      * source of the change.
80      * @param what The attribute or sub-object that changed, if not null.
81      */
82     @Override
dispatchChange(@ullable Watchable what)83     public void dispatchChange(@Nullable Watchable what) {
84         mWatchable.dispatchChange(what);
85     }
86 
87     private final Watcher mWatcher = new Watcher() {
88             @Override
89             public void onChange(@Nullable Watchable what) {
90                 dispatchChange(what);
91             }
92         };
93 
94     /**
95      * Notify listeners that this object has changed.
96      */
onChanged()97     protected void onChanged() {
98         dispatchChange(this);
99     }
100 
101     @Override
addFilter(F f)102     public void addFilter(F f) {
103         super.addFilter(f);
104         f.registerObserver(mWatcher);
105         onChanged();
106     }
107 
108     @Override
removeFilter(F f)109     public void removeFilter(F f) {
110         f.unregisterObserver(mWatcher);
111         super.removeFilter(f);
112         onChanged();
113     }
114 
115     @Override
removeFilterInternal(F f)116     protected void removeFilterInternal(F f) {
117         f.unregisterObserver(mWatcher);
118         super.removeFilterInternal(f);
119         onChanged();
120     }
121 
122     // Sorts a List of IntentFilter objects into descending priority order.
123     @SuppressWarnings("rawtypes")
124     private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter =
125             new Comparator<>() {
126         public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) {
127             final int q1 = o1.getPriority();
128             final int q2 = o2.getPriority();
129             return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
130         }
131     };
132 
133     @Override
134     @SuppressWarnings("unchecked")
sortResults(List<R> results)135     protected void sortResults(List<R> results) {
136         Collections.sort(results, sResolvePrioritySorter);
137     }
138 
139     /**
140      * @see IntentResolver#findFilters(IntentFilter)
141      */
findFilters(WatchedIntentFilter matching)142     public ArrayList<F> findFilters(WatchedIntentFilter matching) {
143         return super.findFilters(matching.getIntentFilter());
144     }
145 
146     // Make <this> a copy of <orig>.  The presumption is that <this> is empty but all
147     // arrays are cleared out explicitly, just to be sure.
copyFrom(WatchedIntentResolver orig)148     protected void copyFrom(WatchedIntentResolver orig) {
149         super.copyFrom(orig);
150     }
151 }
152