blob: 7a4ef2b7bbf22c11ee6b7d650d1ed41c7d543e35 [file] [log] [blame]
Jason Monk0b5e52c2018-04-19 22:14:46 -04001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui;
16
17import android.content.BroadcastReceiver;
18import android.content.ComponentName;
19import android.content.ContentProvider;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.net.Uri;
24import android.os.UserHandle;
25import android.util.ArrayMap;
26import android.util.ArraySet;
27import android.util.Log;
28
29import com.android.internal.annotations.VisibleForTesting;
30import com.android.settingslib.SliceBroadcastRelay;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000031import com.android.systemui.broadcast.BroadcastDispatcher;
32
33import javax.inject.Inject;
34import javax.inject.Singleton;
Jason Monk0b5e52c2018-04-19 22:14:46 -040035
36/**
37 * Allows settings to register certain broadcasts to launch the settings app for pinned slices.
38 * @see SliceBroadcastRelay
39 */
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000040@Singleton
Jason Monk0b5e52c2018-04-19 22:14:46 -040041public class SliceBroadcastRelayHandler extends SystemUI {
42 private static final String TAG = "SliceBroadcastRelay";
43 private static final boolean DEBUG = false;
44
45 private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000046 private final BroadcastDispatcher mBroadcastDispatcher;
Jason Monk0b5e52c2018-04-19 22:14:46 -040047
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000048 @Inject
49 public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher) {
Dave Mankoffa5d8a392019-10-10 12:21:09 -040050 super(context);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000051 mBroadcastDispatcher = broadcastDispatcher;
Dave Mankoffa5d8a392019-10-10 12:21:09 -040052 }
53
Jason Monk0b5e52c2018-04-19 22:14:46 -040054 @Override
55 public void start() {
56 if (DEBUG) Log.d(TAG, "Start");
57 IntentFilter filter = new IntentFilter(SliceBroadcastRelay.ACTION_REGISTER);
58 filter.addAction(SliceBroadcastRelay.ACTION_UNREGISTER);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000059 mBroadcastDispatcher.registerReceiver(mReceiver, filter);
Jason Monk0b5e52c2018-04-19 22:14:46 -040060 }
61
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000062 // This does not use BroadcastDispatcher as the filter may have schemas or mime types.
Jason Monk0b5e52c2018-04-19 22:14:46 -040063 @VisibleForTesting
64 void handleIntent(Intent intent) {
65 if (SliceBroadcastRelay.ACTION_REGISTER.equals(intent.getAction())) {
66 Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
67 ComponentName receiverClass =
68 intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_RECEIVER);
69 IntentFilter filter = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_FILTER);
70 if (DEBUG) Log.d(TAG, "Register " + uri + " " + receiverClass + " " + filter);
71 getOrCreateRelay(uri).register(mContext, receiverClass, filter);
72 } else if (SliceBroadcastRelay.ACTION_UNREGISTER.equals(intent.getAction())) {
73 Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
74 if (DEBUG) Log.d(TAG, "Unregister " + uri);
Sunny Goyala21570c72019-04-19 15:05:41 -070075 BroadcastRelay relay = getAndRemoveRelay(uri);
76 if (relay != null) {
77 relay.unregister(mContext);
78 }
Jason Monk0b5e52c2018-04-19 22:14:46 -040079 }
80 }
81
82 private BroadcastRelay getOrCreateRelay(Uri uri) {
83 BroadcastRelay ret = mRelays.get(uri);
84 if (ret == null) {
85 ret = new BroadcastRelay(uri);
86 mRelays.put(uri, ret);
87 }
88 return ret;
89 }
90
91 private BroadcastRelay getAndRemoveRelay(Uri uri) {
92 return mRelays.remove(uri);
93 }
94
95 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
96 @Override
97 public void onReceive(Context context, Intent intent) {
98 handleIntent(intent);
99 }
100 };
101
102 private static class BroadcastRelay extends BroadcastReceiver {
103
104 private final ArraySet<ComponentName> mReceivers = new ArraySet<>();
105 private final UserHandle mUserId;
Matthew Fritze429d27d2018-05-02 19:43:39 -0700106 private final Uri mUri;
Jason Monk0b5e52c2018-04-19 22:14:46 -0400107
108 public BroadcastRelay(Uri uri) {
109 mUserId = new UserHandle(ContentProvider.getUserIdFromUri(uri));
Matthew Fritze429d27d2018-05-02 19:43:39 -0700110 mUri = uri;
Jason Monk0b5e52c2018-04-19 22:14:46 -0400111 }
112
113 public void register(Context context, ComponentName receiver, IntentFilter filter) {
114 mReceivers.add(receiver);
115 context.registerReceiver(this, filter);
116 }
117
118 public void unregister(Context context) {
119 context.unregisterReceiver(this);
120 }
121
122 @Override
123 public void onReceive(Context context, Intent intent) {
124 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
125 for (ComponentName receiver : mReceivers) {
126 intent.setComponent(receiver);
Matthew Fritze429d27d2018-05-02 19:43:39 -0700127 intent.putExtra(SliceBroadcastRelay.EXTRA_URI, mUri.toString());
Jason Monk0b5e52c2018-04-19 22:14:46 -0400128 if (DEBUG) Log.d(TAG, "Forwarding " + receiver + " " + intent + " " + mUserId);
129 context.sendBroadcastAsUser(intent, mUserId);
130 }
131 }
132 }
133}