TileServices.java revision 66c89c15a0baabf001e69498dbc09903f72cc63d
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; 28d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.os.Looper; 29fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.os.RemoteException; 3066c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport android.os.UserHandle; 31d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.service.quicksettings.IQSService; 32d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.service.quicksettings.Tile; 33fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.service.quicksettings.TileService; 34d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport android.util.ArrayMap; 35fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monkimport android.util.Log; 3666c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.internal.statusbar.StatusBarIcon; 37d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport com.android.systemui.statusbar.phone.QSTileHost; 3866c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.systemui.statusbar.phone.StatusBarIconController; 39d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 40d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.ArrayList; 41d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Collections; 42d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Comparator; 43d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 44d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk/** 45d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Runs the day-to-day operations of which tiles should be bound and when. 46d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk */ 47d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkpublic class TileServices extends IQSService.Stub { 48d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk static final int DEFAULT_MAX_BOUND = 3; 49d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk static final int REDUCED_MAX_BOUND = 1; 50d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 51d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>(); 52d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>(); 53d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final Context mContext; 54d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final Handler mHandler; 5566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk private final Handler mMainHandler; 56d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final QSTileHost mHost; 57d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 58d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private int mMaxBound = DEFAULT_MAX_BOUND; 59d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 60d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public TileServices(QSTileHost host, Looper looper) { 61d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHost = host; 62d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mContext = mHost.getContext(); 63fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mContext.registerReceiver(mRequestListeningReceiver, 64fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk new IntentFilter(TileService.ACTION_REQUEST_LISTENING)); 65d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHandler = new Handler(looper); 6666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler = new Handler(Looper.getMainLooper()); 67d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 68d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 69d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public Context getContext() { 70d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return mContext; 71d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 72d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 73d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public TileServiceManager getTileWrapper(CustomTile tile) { 74d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk ComponentName component = tile.getComponent(); 75d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk TileServiceManager service = onCreateTileService(component); 76d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 77d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mServices.put(tile, service); 78d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mTiles.put(component, tile); 79d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 80d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return service; 81d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 82d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 83d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk protected TileServiceManager onCreateTileService(ComponentName component) { 84d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return new TileServiceManager(this, mHandler, component); 85d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 86d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 87d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void freeService(CustomTile tile, TileServiceManager service) { 88d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 89d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk service.setBindAllowed(false); 90d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mServices.remove(tile); 91d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mTiles.remove(tile.getComponent()); 9266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final String slot = tile.getComponent().getClassName(); 9366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler.post(new Runnable() { 9466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 9566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void run() { 9666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mHost.getIconController().removeIcon(slot); 9766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 9866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk }); 99d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 100d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 101d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 102d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void setMemoryPressure(boolean memoryPressure) { 103d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mMaxBound = memoryPressure ? REDUCED_MAX_BOUND : DEFAULT_MAX_BOUND; 104d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk recalculateBindAllowance(); 105d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 106d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 107d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void recalculateBindAllowance() { 108d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk final ArrayList<TileServiceManager> services; 109d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 110d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services = new ArrayList<>(mServices.values()); 111d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 112d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk final int N = services.size(); 113d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (N > mMaxBound) { 114d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk long currentTime = System.currentTimeMillis(); 115d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Precalculate the priority of services for binding. 116d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk for (int i = 0; i < N; i++) { 117d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).calculateBindPriority(currentTime); 118d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 119d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Sort them so we can bind the most important first. 120d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk Collections.sort(services, SERVICE_SORT); 121d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 122d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk int i; 123d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Allow mMaxBound items to bind. 124d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk for (i = 0; i < mMaxBound && i < N; i++) { 125d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).setBindAllowed(true); 126d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 127d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // The rest aren't allowed to bind for now. 128d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk while (i < N) { 129d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).setBindAllowed(false); 130d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk i++; 131d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 132d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 133d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 134d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private void verifyCaller(String packageName) { 135d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk try { 136e06b4d1d9f718b9fe02980fea794a36831a16db2Jeff Sharkey int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 137d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk Binder.getCallingUserHandle().getIdentifier()); 138d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (Binder.getCallingUid() != uid) { 139d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk throw new SecurityException("Component outside caller's uid"); 140d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 141d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } catch (PackageManager.NameNotFoundException e) { 142d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk throw new SecurityException(e); 143d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 144d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 145d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 146fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk private void requestListening(ComponentName component) { 147fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 148fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk CustomTile customTile = getTileForComponent(component); 149fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (customTile == null) { 150fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk Log.d("TileServices", "Couldn't find tile for " + component); 151fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return; 152fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 153fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk TileServiceManager service = mServices.get(customTile); 154fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (service.getType() != TileService.TILE_MODE_ACTIVE) { 155fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return; 156fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 157fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk service.setBindRequested(true); 158fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk try { 159fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk service.getTileService().onStartListening(); 160fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } catch (RemoteException e) { 161fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 162fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 163fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 164fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 165fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk @Override 166fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk public void setTileMode(ComponentName component, int mode) { 167fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk verifyCaller(component.getPackageName()); 168fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk CustomTile customTile = getTileForComponent(component); 169fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (customTile != null) { 170fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 171fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mServices.get(customTile).setType(mode); 172fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 173fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 174fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 175fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 176d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 177d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void updateQsTile(Tile tile) { 17866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ComponentName componentName = tile.getComponentName(); 17966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(componentName.getPackageName()); 18066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 181d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (customTile != null) { 182fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 183fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mServices.get(customTile).setLastUpdate(System.currentTimeMillis()); 184fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 185d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.updateState(tile); 186d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.refreshState(); 187d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 188d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 189d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 190d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 191d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void onShowDialog(Tile tile) { 19266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ComponentName componentName = tile.getComponentName(); 19366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(componentName.getPackageName()); 19466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 195d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (customTile != null) { 196d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.onDialogShown(); 197d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHost.collapsePanels(); 198d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 199d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 200d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 20166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 20266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void updateStatusIcon(Tile tile, Icon icon, String contentDescription) { 20366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final ComponentName componentName = tile.getComponentName(); 20466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk String packageName = componentName.getPackageName(); 20566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(packageName); 20666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 20766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk if (customTile != null) { 20866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk try { 20966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk UserHandle userHandle = getCallingUserHandle(); 21066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk PackageInfo info = mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, 21166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk userHandle.getIdentifier()); 21266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk if (info.applicationInfo.isSystemApp()) { 21366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final StatusBarIcon statusIcon = icon != null 21466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ? new StatusBarIcon(userHandle, packageName, icon, 0, 0, 21566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk contentDescription) 21666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk : null; 21766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler.post(new Runnable() { 21866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 21966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void run() { 22066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk StatusBarIconController iconController = mHost.getIconController(); 22166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk iconController.setIcon(componentName.getClassName(), statusIcon); 22266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk iconController.setExternalIcon(componentName.getClassName()); 22366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 22466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk }); 22566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 22666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } catch (PackageManager.NameNotFoundException e) { 22766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 22866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 22966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 23066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk 231d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private CustomTile getTileForComponent(ComponentName component) { 232fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 233fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return mTiles.get(component); 234fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 235d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 236d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 237fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() { 238fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk @Override 239fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk public void onReceive(Context context, Intent intent) { 240fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { 241fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk requestListening( 242fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk (ComponentName) intent.getParcelableExtra(TileService.EXTRA_COMPONENT)); 243fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 244fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 245fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk }; 246fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 247d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private static final Comparator<TileServiceManager> SERVICE_SORT = 248d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk new Comparator<TileServiceManager>() { 249d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 250d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public int compare(TileServiceManager left, TileServiceManager right) { 251d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return -Integer.compare(left.getBindPriority(), right.getBindPriority()); 252d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 253d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk }; 254d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk} 255