TileServices.java revision c673fbc2c2eb37037dae9a8c55b1588ab398a116
1d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk/*
2d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Copyright (C) 2015 The Android Open Source Project
3d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk *
4d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Licensed under the Apache License, Version 2.0 (the "License");
5d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * you may not use this file except in compliance with the License.
6d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * You may obtain a copy of the License at
7d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk *
8d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk *      http://www.apache.org/licenses/LICENSE-2.0
9d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk *
10d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Unless required by applicable law or agreed to in writing, software
11d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * distributed under the License is distributed on an "AS IS" BASIS,
12d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * See the License for the specific language governing permissions and
14d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * limitations under the License
15d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk */
16d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkpackage com.android.systemui.qs.external;
17d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
18fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.content.BroadcastReceiver;
19d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.content.ComponentName;
20d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.content.Context;
21fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.content.Intent;
22fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.content.IntentFilter;
2366c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport android.content.pm.PackageInfo;
24d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.content.pm.PackageManager;
2566c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport android.graphics.drawable.Icon;
26d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.os.Binder;
27d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.os.Handler;
28ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monkimport android.os.IBinder;
29d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.os.Looper;
30fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.os.RemoteException;
3166c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport android.os.UserHandle;
32d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.service.quicksettings.IQSService;
33d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.service.quicksettings.Tile;
34fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.service.quicksettings.TileService;
35d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.util.ArrayMap;
36fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.util.Log;
37c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson
3866c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.internal.statusbar.StatusBarIcon;
399c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monkimport com.android.systemui.Dependency;
40e5b770e47d44a40d412c7d42010b2cf67920d9e3Jason Monkimport com.android.systemui.qs.QSTileHost;
4166c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.systemui.statusbar.phone.StatusBarIconController;
429429513cc3ea6e58e330865bd621b57cb3477551Jason Monkimport com.android.systemui.statusbar.policy.KeyguardMonitor;
43d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
44d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.ArrayList;
45d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Collections;
46d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Comparator;
47d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
48d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk/**
49d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Runs the day-to-day operations of which tiles should be bound and when.
50d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk */
51d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkpublic class TileServices extends IQSService.Stub {
52d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    static final int DEFAULT_MAX_BOUND = 3;
53d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    static final int REDUCED_MAX_BOUND = 1;
54d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
55d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>();
56d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>();
57ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    private final ArrayMap<IBinder, CustomTile> mTokenMap = new ArrayMap<>();
58d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private final Context mContext;
59d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private final Handler mHandler;
6066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk    private final Handler mMainHandler;
61d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private final QSTileHost mHost;
62d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
63d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private int mMaxBound = DEFAULT_MAX_BOUND;
64d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
65d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public TileServices(QSTileHost host, Looper looper) {
66d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        mHost = host;
67d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        mContext = mHost.getContext();
68fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        mContext.registerReceiver(mRequestListeningReceiver,
69fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                new IntentFilter(TileService.ACTION_REQUEST_LISTENING));
70d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        mHandler = new Handler(looper);
7166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk        mMainHandler = new Handler(Looper.getMainLooper());
72d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
73d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
74d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public Context getContext() {
75d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        return mContext;
76d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
77d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
7807f55a2a04f8bfbb1702ca226f394607b5130908Jason Monk    public QSTileHost getHost() {
7907f55a2a04f8bfbb1702ca226f394607b5130908Jason Monk        return mHost;
8007f55a2a04f8bfbb1702ca226f394607b5130908Jason Monk    }
8107f55a2a04f8bfbb1702ca226f394607b5130908Jason Monk
82d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public TileServiceManager getTileWrapper(CustomTile tile) {
83d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        ComponentName component = tile.getComponent();
84a3453b8bd9af44566c6a31fd0156cc76e6028f6dJason Monk        TileServiceManager service = onCreateTileService(component, tile.getQsTile());
85d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        synchronized (mServices) {
86d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            mServices.put(tile, service);
87d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            mTiles.put(component, tile);
88ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk            mTokenMap.put(service.getToken(), tile);
89d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
90d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        return service;
91d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
92d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
93a3453b8bd9af44566c6a31fd0156cc76e6028f6dJason Monk    protected TileServiceManager onCreateTileService(ComponentName component, Tile tile) {
94a3453b8bd9af44566c6a31fd0156cc76e6028f6dJason Monk        return new TileServiceManager(this, mHandler, component, tile);
95d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
96d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
97d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public void freeService(CustomTile tile, TileServiceManager service) {
98d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        synchronized (mServices) {
99d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            service.setBindAllowed(false);
10007f55a2a04f8bfbb1702ca226f394607b5130908Jason Monk            service.handleDestroy();
101d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            mServices.remove(tile);
102ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk            mTokenMap.remove(service.getToken());
103d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            mTiles.remove(tile.getComponent());
10466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk            final String slot = tile.getComponent().getClassName();
1054cfd8c740dee6cd8fe361a59487acde4e465f31fJason Monk            mMainHandler.post(() -> mHost.getIconController().removeIcon(slot));
106d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
107d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
108d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
109d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public void setMemoryPressure(boolean memoryPressure) {
110d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        mMaxBound = memoryPressure ? REDUCED_MAX_BOUND : DEFAULT_MAX_BOUND;
111d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        recalculateBindAllowance();
112d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
113d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
114d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    public void recalculateBindAllowance() {
115d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        final ArrayList<TileServiceManager> services;
116d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        synchronized (mServices) {
117d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            services = new ArrayList<>(mServices.values());
118d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
119d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        final int N = services.size();
120d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        if (N > mMaxBound) {
121d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            long currentTime = System.currentTimeMillis();
122d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            // Precalculate the priority of services for binding.
123d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            for (int i = 0; i < N; i++) {
124d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk                services.get(i).calculateBindPriority(currentTime);
125d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            }
126d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            // Sort them so we can bind the most important first.
127d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            Collections.sort(services, SERVICE_SORT);
128d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
129d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        int i;
130d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        // Allow mMaxBound items to bind.
131d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        for (i = 0; i < mMaxBound && i < N; i++) {
132d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            services.get(i).setBindAllowed(true);
133d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
134d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        // The rest aren't allowed to bind for now.
135d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        while (i < N) {
136d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            services.get(i).setBindAllowed(false);
137d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            i++;
138d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
139d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
140d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
141ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    private void verifyCaller(CustomTile tile) {
142d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        try {
143ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk            String packageName = tile.getComponent().getPackageName();
144e06b4d1d9f718b9fe02980fea794a36831a16db2Jeff Sharkey            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
145d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk                    Binder.getCallingUserHandle().getIdentifier());
146d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            if (Binder.getCallingUid() != uid) {
147d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk                throw new SecurityException("Component outside caller's uid");
148d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            }
149d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        } catch (PackageManager.NameNotFoundException e) {
150d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            throw new SecurityException(e);
151d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
152d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
153d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
154fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk    private void requestListening(ComponentName component) {
155fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        synchronized (mServices) {
156fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            CustomTile customTile = getTileForComponent(component);
157fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            if (customTile == null) {
158fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                Log.d("TileServices", "Couldn't find tile for " + component);
159fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                return;
160fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            }
161fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            TileServiceManager service = mServices.get(customTile);
16297d2272be0bf3e77474e7ff9984217dfe247f4d0Jason Monk            if (!service.isActiveTile()) {
163fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                return;
164fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            }
165fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            service.setBindRequested(true);
166fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            try {
167fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                service.getTileService().onStartListening();
168fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            } catch (RemoteException e) {
169fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            }
170fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        }
171fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk    }
172fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk
173fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk    @Override
174ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void updateQsTile(Tile tile, IBinder token) {
175ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
176d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        if (customTile != null) {
177016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
178fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            synchronized (mServices) {
1791c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk                final TileServiceManager tileServiceManager = mServices.get(customTile);
1801c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk                tileServiceManager.clearPendingBind();
1811c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk                tileServiceManager.setLastUpdate(System.currentTimeMillis());
182fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            }
183d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            customTile.updateState(tile);
184d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            customTile.refreshState();
185d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
186d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
187d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
188d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    @Override
189ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void onStartSuccessful(IBinder token) {
190ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
1911c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk        if (customTile != null) {
192016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
1931c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk            synchronized (mServices) {
1941c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk                final TileServiceManager tileServiceManager = mServices.get(customTile);
1951c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk                tileServiceManager.clearPendingBind();
1961c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk            }
1971c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk            customTile.refreshState();
1981c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk        }
1991c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk    }
2001c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk
2011c2fea8df7054d1bc23945c38460a123ce453c4aJason Monk    @Override
202ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void onShowDialog(IBinder token) {
203ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
204d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        if (customTile != null) {
205016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
206d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            customTile.onDialogShown();
207c673fbc2c2eb37037dae9a8c55b1588ab398a116Yoshinori Hirano            mHost.forceCollapsePanels();
20834a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk            mServices.get(customTile).setShowingDialog(true);
20934a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk        }
21034a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk    }
21134a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk
21234a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk    @Override
213ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void onDialogHidden(IBinder token) {
214ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
21534a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk        if (customTile != null) {
216016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
21734a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk            mServices.get(customTile).setShowingDialog(false);
21834a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk            customTile.onDialogHidden();
219d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
220d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
221d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
22266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk    @Override
223ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void onStartActivity(IBinder token) {
224ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
2259429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        if (customTile != null) {
226016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
227c673fbc2c2eb37037dae9a8c55b1588ab398a116Yoshinori Hirano            mHost.forceCollapsePanels();
2289429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        }
2299429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    }
2309429513cc3ea6e58e330865bd621b57cb3477551Jason Monk
2319429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    @Override
232ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void updateStatusIcon(IBinder token, Icon icon, String contentDescription) {
233ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
23466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk        if (customTile != null) {
235016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
23666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk            try {
237ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk                ComponentName componentName = customTile.getComponent();
238ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk                String packageName = componentName.getPackageName();
23966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                UserHandle userHandle = getCallingUserHandle();
24066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                PackageInfo info = mContext.getPackageManager().getPackageInfoAsUser(packageName, 0,
24166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                        userHandle.getIdentifier());
24266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                if (info.applicationInfo.isSystemApp()) {
24366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                    final StatusBarIcon statusIcon = icon != null
24466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                            ? new StatusBarIcon(userHandle, packageName, icon, 0, 0,
24566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                                    contentDescription)
24666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                            : null;
24766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                    mMainHandler.post(new Runnable() {
24866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                        @Override
24966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                        public void run() {
25066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                            StatusBarIconController iconController = mHost.getIconController();
25166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                            iconController.setIcon(componentName.getClassName(), statusIcon);
25266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                            iconController.setExternalIcon(componentName.getClassName());
25366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                        }
25466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                    });
25566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk                }
25666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk            } catch (PackageManager.NameNotFoundException e) {
25766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk            }
25866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk        }
25966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk    }
26066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk
2619429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    @Override
262ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public Tile getTile(IBinder token) {
263ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
2648753e184f967d1db91de34cb66aae0a977259a60Jason Monk        if (customTile != null) {
265016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
2668753e184f967d1db91de34cb66aae0a977259a60Jason Monk            return customTile.getQsTile();
2678753e184f967d1db91de34cb66aae0a977259a60Jason Monk        }
2688753e184f967d1db91de34cb66aae0a977259a60Jason Monk        return null;
2698753e184f967d1db91de34cb66aae0a977259a60Jason Monk    }
2708753e184f967d1db91de34cb66aae0a977259a60Jason Monk
2718753e184f967d1db91de34cb66aae0a977259a60Jason Monk    @Override
272ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    public void startUnlockAndRun(IBinder token) {
273ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        CustomTile customTile = getTileForToken(token);
2749429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        if (customTile != null) {
275016bc90331cd8b7dd3b8ec58b4ea6f64d3953bbaJason Monk            verifyCaller(customTile);
2769429513cc3ea6e58e330865bd621b57cb3477551Jason Monk            customTile.startUnlockAndRun();
2779429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        }
2789429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    }
2799429513cc3ea6e58e330865bd621b57cb3477551Jason Monk
2809429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    @Override
2819429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    public boolean isLocked() {
2829c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk        KeyguardMonitor keyguardMonitor = Dependency.get(KeyguardMonitor.class);
2839429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        return keyguardMonitor.isShowing();
2849429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    }
2859429513cc3ea6e58e330865bd621b57cb3477551Jason Monk
2869429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    @Override
2879429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    public boolean isSecure() {
2889c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk        KeyguardMonitor keyguardMonitor = Dependency.get(KeyguardMonitor.class);
2899429513cc3ea6e58e330865bd621b57cb3477551Jason Monk        return keyguardMonitor.isSecure() && keyguardMonitor.isShowing();
2909429513cc3ea6e58e330865bd621b57cb3477551Jason Monk    }
2919429513cc3ea6e58e330865bd621b57cb3477551Jason Monk
292ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    private CustomTile getTileForToken(IBinder token) {
293ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        synchronized (mServices) {
294ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk            return mTokenMap.get(token);
295ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk        }
296ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk    }
297ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8Jason Monk
298d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private CustomTile getTileForComponent(ComponentName component) {
299fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        synchronized (mServices) {
300fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            return mTiles.get(component);
301fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        }
302d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    }
303d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk
3048852905b0b3837e326127c6dfef6f699124ce715Jason Monk    public void destroy() {
305809aadf69e087eb951e94d19e1d4705e029be68cJason Monk        synchronized (mServices) {
306809aadf69e087eb951e94d19e1d4705e029be68cJason Monk            mServices.values().forEach(service -> service.handleDestroy());
307809aadf69e087eb951e94d19e1d4705e029be68cJason Monk            mContext.unregisterReceiver(mRequestListeningReceiver);
308809aadf69e087eb951e94d19e1d4705e029be68cJason Monk        }
3098852905b0b3837e326127c6dfef6f699124ce715Jason Monk    }
3108852905b0b3837e326127c6dfef6f699124ce715Jason Monk
311fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk    private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() {
312fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        @Override
313fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        public void onReceive(Context context, Intent intent) {
314fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) {
315fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk                requestListening(
3161a74942fbfa36bf62013b51d8ad9fb4c0e44c6f4Jeff Sharkey                        (ComponentName) intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME));
317fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk            }
318fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk        }
319fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk    };
320fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk
321d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    private static final Comparator<TileServiceManager> SERVICE_SORT =
322d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            new Comparator<TileServiceManager>() {
323d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        @Override
324d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        public int compare(TileServiceManager left, TileServiceManager right) {
325d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk            return -Integer.compare(left.getBindPriority(), right.getBindPriority());
326d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk        }
327d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk    };
328d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk}
329