• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.nearby.common.servicemonitor;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.net.Uri;
24 import android.os.Handler;
25 import android.os.Looper;
26 
27 import com.android.modules.utils.BackgroundThread;
28 
29 import java.util.Objects;
30 
31 /**
32  * This is mostly from frameworks PackageMonitor.
33  * Helper class for watching somePackagesChanged.
34  */
35 public abstract class PackageWatcher extends BroadcastReceiver {
36     static final String TAG = "PackageWatcher";
37     static final IntentFilter sPackageFilt = new IntentFilter();
38     static final IntentFilter sNonDataFilt = new IntentFilter();
39     static final IntentFilter sExternalFilt = new IntentFilter();
40 
41     static {
42         sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
43         sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
44         sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
45         sPackageFilt.addDataScheme("package");
46         sNonDataFilt.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
47         sNonDataFilt.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
48         sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
49         sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
50     }
51 
52     Context mRegisteredContext;
53     Handler mRegisteredHandler;
54     boolean mSomePackagesChanged;
55 
PackageWatcher()56     public PackageWatcher() {
57     }
58 
register(Context context, Looper thread, boolean externalStorage)59     void register(Context context, Looper thread, boolean externalStorage) {
60         register(context, externalStorage,
61                 (thread == null) ? BackgroundThread.getHandler() : new Handler(thread));
62     }
63 
register(Context context, boolean externalStorage, Handler handler)64     void register(Context context, boolean externalStorage, Handler handler) {
65         if (mRegisteredContext != null) {
66             throw new IllegalStateException("Already registered");
67         }
68         mRegisteredContext = context;
69         mRegisteredHandler = Objects.requireNonNull(handler);
70         context.registerReceiverForAllUsers(this, sPackageFilt, null, mRegisteredHandler);
71         context.registerReceiverForAllUsers(this, sNonDataFilt, null, mRegisteredHandler);
72         if (externalStorage) {
73             context.registerReceiverForAllUsers(this, sExternalFilt, null, mRegisteredHandler);
74         }
75     }
76 
unregister()77     void unregister() {
78         if (mRegisteredContext == null) {
79             throw new IllegalStateException("Not registered");
80         }
81         mRegisteredContext.unregisterReceiver(this);
82         mRegisteredContext = null;
83     }
84 
85     // Called when some package has been changed.
onSomePackagesChanged()86     abstract void onSomePackagesChanged();
87 
getPackageName(Intent intent)88     String getPackageName(Intent intent) {
89         Uri uri = intent.getData();
90         String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
91         return pkg;
92     }
93 
94     @Override
onReceive(Context context, Intent intent)95     public void onReceive(Context context, Intent intent) {
96         mSomePackagesChanged = false;
97 
98         String action = intent.getAction();
99         if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
100             // We consider something to have changed regardless of whether
101             // this is just an update, because the update is now finished
102             // and the contents of the package may have changed.
103             mSomePackagesChanged = true;
104         } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
105             String pkg = getPackageName(intent);
106             if (pkg != null) {
107                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
108                     mSomePackagesChanged = true;
109                 }
110             }
111         } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
112             String pkg = getPackageName(intent);
113             if (pkg != null) {
114                 mSomePackagesChanged = true;
115             }
116         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
117             mSomePackagesChanged = true;
118         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
119             mSomePackagesChanged = true;
120         } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
121             mSomePackagesChanged = true;
122         } else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) {
123             mSomePackagesChanged = true;
124         }
125 
126         if (mSomePackagesChanged) {
127             onSomePackagesChanged();
128         }
129     }
130 }
131