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 import android.content.IntentFilter;
22 
23 import com.android.server.IntentResolver;
24 import com.android.server.pm.snapshot.PackageDataSnapshot;
25 import com.android.server.utils.Snappable;
26 import com.android.server.utils.Watchable;
27 import com.android.server.utils.WatchableImpl;
28 import com.android.server.utils.Watcher;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.Comparator;
33 import java.util.List;
34 
35 /**
36  * A watched {@link IntentResolver}.  The parameters are inherited from the superclass.
37  * @param <F> The filter type
38  * @param <R> The resolver type.
39  * {@hide}
40  */
41 public abstract class WatchedIntentResolver<F extends WatchedIntentFilter,
42                                             R extends WatchedIntentFilter>
43         extends IntentResolver<F, R>
44         implements Watchable, Snappable {
45 
46     /**
47      * Watchable machinery
48      */
49     private final Watchable mWatchable = new WatchableImpl();
50 
51     /**
52      * Register an observer to receive change notifications.
53      * @param observer The observer to register.
54      */
55     @Override
registerObserver(@onNull Watcher observer)56     public void registerObserver(@NonNull Watcher observer) {
57         mWatchable.registerObserver(observer);
58     }
59 
60     /**
61      * Unregister the observer, which will no longer receive change notifications.
62      * @param observer The observer to unregister.
63      */
64     @Override
unregisterObserver(@onNull Watcher observer)65     public void unregisterObserver(@NonNull Watcher observer) {
66         mWatchable.unregisterObserver(observer);
67     }
68 
69     /**
70      * Return true if the {@link Watcher) is a registered observer.
71      * @param observer A {@link Watcher} that might be registered
72      * @return true if the observer is registered with this {@link Watchable}.
73      */
74     @Override
isRegisteredObserver(@onNull Watcher observer)75     public boolean isRegisteredObserver(@NonNull Watcher observer) {
76         return mWatchable.isRegisteredObserver(observer);
77     }
78 
79     /**
80      * Notify listeners that the object has changd.  The argument is a hint as to the
81      * source of the change.
82      * @param what The attribute or sub-object that changed, if not null.
83      */
84     @Override
dispatchChange(@ullable Watchable what)85     public void dispatchChange(@Nullable Watchable what) {
86         mWatchable.dispatchChange(what);
87     }
88 
89     private final Watcher mWatcher = new Watcher() {
90             @Override
91             public void onChange(@Nullable Watchable what) {
92                 dispatchChange(what);
93             }
94         };
95 
96     /**
97      * Notify listeners that this object has changed.
98      */
onChanged()99     protected void onChanged() {
100         dispatchChange(this);
101     }
102 
103     @Override
addFilter(@ullable PackageDataSnapshot snapshot, F f)104     public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
105         super.addFilter(snapshot, f);
106         f.registerObserver(mWatcher);
107         onChanged();
108     }
109 
110     @Override
removeFilter(F f)111     public void removeFilter(F f) {
112         f.unregisterObserver(mWatcher);
113         super.removeFilter(f);
114         onChanged();
115     }
116 
117     @Override
removeFilterInternal(F f)118     protected void removeFilterInternal(F f) {
119         f.unregisterObserver(mWatcher);
120         super.removeFilterInternal(f);
121         onChanged();
122     }
123 
124     // Sorts a List of IntentFilter objects into descending priority order.
125     @SuppressWarnings("rawtypes")
126     private static final Comparator<WatchedIntentFilter> sResolvePrioritySorter =
127             new Comparator<>() {
128         public int compare(WatchedIntentFilter o1, WatchedIntentFilter o2) {
129             final int q1 = o1.getPriority();
130             final int q2 = o2.getPriority();
131             return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
132         }
133     };
134 
135     @Override
136     @SuppressWarnings("unchecked")
sortResults(List<R> results)137     protected void sortResults(List<R> results) {
138         Collections.sort(results, sResolvePrioritySorter);
139     }
140 
141     /**
142      * @see IntentResolver#findFilters(IntentFilter)
143      */
findFilters(WatchedIntentFilter matching)144     public ArrayList<F> findFilters(WatchedIntentFilter matching) {
145         return super.findFilters(matching.getIntentFilter());
146     }
147 
148     // Make <this> a copy of <orig>.  The presumption is that <this> is empty but all
149     // arrays are cleared out explicitly, just to be sure.
copyFrom(WatchedIntentResolver orig)150     protected void copyFrom(WatchedIntentResolver orig) {
151         super.copyFrom(orig);
152     }
153 }
154