TileServices.java revision 34a5cef6298cc44fc0614c4747c4b17137cff441
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; 36c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 3766c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.internal.statusbar.StatusBarIcon; 38d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport com.android.systemui.statusbar.phone.QSTileHost; 3966c89c15a0baabf001e69498dbc09903f72cc63dJason Monkimport com.android.systemui.statusbar.phone.StatusBarIconController; 409429513cc3ea6e58e330865bd621b57cb3477551Jason Monkimport com.android.systemui.statusbar.policy.KeyguardMonitor; 41d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 42d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.ArrayList; 43d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Collections; 44d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkimport java.util.Comparator; 45d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 46d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk/** 47d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk * Runs the day-to-day operations of which tiles should be bound and when. 48d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk */ 49d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monkpublic class TileServices extends IQSService.Stub { 50d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk static final int DEFAULT_MAX_BOUND = 3; 51d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk static final int REDUCED_MAX_BOUND = 1; 52d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 53d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>(); 54d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>(); 55d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final Context mContext; 56d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final Handler mHandler; 5766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk private final Handler mMainHandler; 58d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private final QSTileHost mHost; 59d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 60d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private int mMaxBound = DEFAULT_MAX_BOUND; 61d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 62d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public TileServices(QSTileHost host, Looper looper) { 63d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHost = host; 64d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mContext = mHost.getContext(); 65fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mContext.registerReceiver(mRequestListeningReceiver, 66fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk new IntentFilter(TileService.ACTION_REQUEST_LISTENING)); 67d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHandler = new Handler(looper); 6866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler = new Handler(Looper.getMainLooper()); 69d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 70d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 71d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public Context getContext() { 72d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return mContext; 73d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 74d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 75d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public TileServiceManager getTileWrapper(CustomTile tile) { 76d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk ComponentName component = tile.getComponent(); 77d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk TileServiceManager service = onCreateTileService(component); 78d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 79d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mServices.put(tile, service); 80d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mTiles.put(component, tile); 81d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 82d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return service; 83d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 84d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 85d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk protected TileServiceManager onCreateTileService(ComponentName component) { 86d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return new TileServiceManager(this, mHandler, component); 87d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 88d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 89d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void freeService(CustomTile tile, TileServiceManager service) { 90d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 91d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk service.setBindAllowed(false); 92d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mServices.remove(tile); 93d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mTiles.remove(tile.getComponent()); 9466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final String slot = tile.getComponent().getClassName(); 9566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler.post(new Runnable() { 9666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 9766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void run() { 9866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mHost.getIconController().removeIcon(slot); 9966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 10066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk }); 101d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 102d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 103d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 104d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void setMemoryPressure(boolean memoryPressure) { 105d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mMaxBound = memoryPressure ? REDUCED_MAX_BOUND : DEFAULT_MAX_BOUND; 106d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk recalculateBindAllowance(); 107d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 108d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 109d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void recalculateBindAllowance() { 110d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk final ArrayList<TileServiceManager> services; 111d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk synchronized (mServices) { 112d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services = new ArrayList<>(mServices.values()); 113d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 114d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk final int N = services.size(); 115d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (N > mMaxBound) { 116d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk long currentTime = System.currentTimeMillis(); 117d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Precalculate the priority of services for binding. 118d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk for (int i = 0; i < N; i++) { 119d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).calculateBindPriority(currentTime); 120d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 121d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Sort them so we can bind the most important first. 122d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk Collections.sort(services, SERVICE_SORT); 123d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 124d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk int i; 125d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // Allow mMaxBound items to bind. 126d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk for (i = 0; i < mMaxBound && i < N; i++) { 127d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).setBindAllowed(true); 128d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 129d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk // The rest aren't allowed to bind for now. 130d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk while (i < N) { 131d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk services.get(i).setBindAllowed(false); 132d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk i++; 133d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 134d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 135d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 136d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private void verifyCaller(String packageName) { 137d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk try { 138e06b4d1d9f718b9fe02980fea794a36831a16db2Jeff Sharkey int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 139d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk Binder.getCallingUserHandle().getIdentifier()); 140d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (Binder.getCallingUid() != uid) { 141d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk throw new SecurityException("Component outside caller's uid"); 142d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 143d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } catch (PackageManager.NameNotFoundException e) { 144d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk throw new SecurityException(e); 145d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 146d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 147d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 148fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk private void requestListening(ComponentName component) { 149fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 150fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk CustomTile customTile = getTileForComponent(component); 151fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (customTile == null) { 152fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk Log.d("TileServices", "Couldn't find tile for " + component); 153fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return; 154fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 155fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk TileServiceManager service = mServices.get(customTile); 156fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (service.getType() != TileService.TILE_MODE_ACTIVE) { 157fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return; 158fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 159fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk service.setBindRequested(true); 160fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk try { 161fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk service.getTileService().onStartListening(); 162fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } catch (RemoteException e) { 163fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 164fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 165fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 166fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 167fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk @Override 168fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk public void setTileMode(ComponentName component, int mode) { 169fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk verifyCaller(component.getPackageName()); 170fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk CustomTile customTile = getTileForComponent(component); 171fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (customTile != null) { 172fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 173fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mServices.get(customTile).setType(mode); 174fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 175fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 176fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 177fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 178d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 179d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void updateQsTile(Tile tile) { 18066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ComponentName componentName = tile.getComponentName(); 18166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(componentName.getPackageName()); 18266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 183d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (customTile != null) { 184fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 185fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk mServices.get(customTile).setLastUpdate(System.currentTimeMillis()); 186fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 187d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.updateState(tile); 188d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.refreshState(); 189d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 190d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 191d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 192d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 193d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public void onShowDialog(Tile tile) { 19466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ComponentName componentName = tile.getComponentName(); 19566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(componentName.getPackageName()); 19666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 197d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk if (customTile != null) { 198d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk customTile.onDialogShown(); 199d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk mHost.collapsePanels(); 20034a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk mServices.get(customTile).setShowingDialog(true); 20134a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk } 20234a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk } 20334a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk 20434a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk @Override 20534a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk public void onDialogHidden(Tile tile) { 20634a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk ComponentName componentName = tile.getComponentName(); 20734a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk verifyCaller(componentName.getPackageName()); 20834a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk CustomTile customTile = getTileForComponent(componentName); 20934a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk if (customTile != null) { 21034a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk mServices.get(customTile).setShowingDialog(false); 21134a5cef6298cc44fc0614c4747c4b17137cff441Jason Monk customTile.onDialogHidden(); 212d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 213d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 214d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 21566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 2169429513cc3ea6e58e330865bd621b57cb3477551Jason Monk public void onStartActivity(Tile tile) { 2179429513cc3ea6e58e330865bd621b57cb3477551Jason Monk ComponentName componentName = tile.getComponentName(); 2189429513cc3ea6e58e330865bd621b57cb3477551Jason Monk verifyCaller(componentName.getPackageName()); 2199429513cc3ea6e58e330865bd621b57cb3477551Jason Monk CustomTile customTile = getTileForComponent(componentName); 2209429513cc3ea6e58e330865bd621b57cb3477551Jason Monk if (customTile != null) { 2219429513cc3ea6e58e330865bd621b57cb3477551Jason Monk mHost.collapsePanels(); 2229429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2239429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2249429513cc3ea6e58e330865bd621b57cb3477551Jason Monk 2259429513cc3ea6e58e330865bd621b57cb3477551Jason Monk @Override 22666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void updateStatusIcon(Tile tile, Icon icon, String contentDescription) { 22766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final ComponentName componentName = tile.getComponentName(); 22866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk String packageName = componentName.getPackageName(); 22966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk verifyCaller(packageName); 23066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk CustomTile customTile = getTileForComponent(componentName); 23166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk if (customTile != null) { 23266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk try { 23366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk UserHandle userHandle = getCallingUserHandle(); 23466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk PackageInfo info = mContext.getPackageManager().getPackageInfoAsUser(packageName, 0, 23566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk userHandle.getIdentifier()); 23666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk if (info.applicationInfo.isSystemApp()) { 23766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk final StatusBarIcon statusIcon = icon != null 23866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk ? new StatusBarIcon(userHandle, packageName, icon, 0, 0, 23966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk contentDescription) 24066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk : null; 24166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk mMainHandler.post(new Runnable() { 24266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk @Override 24366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk public void run() { 24466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk StatusBarIconController iconController = mHost.getIconController(); 24566c89c15a0baabf001e69498dbc09903f72cc63dJason Monk iconController.setIcon(componentName.getClassName(), statusIcon); 24666c89c15a0baabf001e69498dbc09903f72cc63dJason Monk iconController.setExternalIcon(componentName.getClassName()); 24766c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 24866c89c15a0baabf001e69498dbc09903f72cc63dJason Monk }); 24966c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 25066c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } catch (PackageManager.NameNotFoundException e) { 25166c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 25266c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 25366c89c15a0baabf001e69498dbc09903f72cc63dJason Monk } 25466c89c15a0baabf001e69498dbc09903f72cc63dJason Monk 2559429513cc3ea6e58e330865bd621b57cb3477551Jason Monk @Override 2569429513cc3ea6e58e330865bd621b57cb3477551Jason Monk public void startUnlockAndRun(Tile tile) { 2579429513cc3ea6e58e330865bd621b57cb3477551Jason Monk ComponentName componentName = tile.getComponentName(); 2589429513cc3ea6e58e330865bd621b57cb3477551Jason Monk verifyCaller(componentName.getPackageName()); 2599429513cc3ea6e58e330865bd621b57cb3477551Jason Monk CustomTile customTile = getTileForComponent(componentName); 2609429513cc3ea6e58e330865bd621b57cb3477551Jason Monk if (customTile != null) { 2619429513cc3ea6e58e330865bd621b57cb3477551Jason Monk customTile.startUnlockAndRun(); 2629429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2639429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2649429513cc3ea6e58e330865bd621b57cb3477551Jason Monk 2659429513cc3ea6e58e330865bd621b57cb3477551Jason Monk @Override 2669429513cc3ea6e58e330865bd621b57cb3477551Jason Monk public boolean isLocked() { 2679429513cc3ea6e58e330865bd621b57cb3477551Jason Monk KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor(); 2689429513cc3ea6e58e330865bd621b57cb3477551Jason Monk return keyguardMonitor.isShowing(); 2699429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2709429513cc3ea6e58e330865bd621b57cb3477551Jason Monk 2719429513cc3ea6e58e330865bd621b57cb3477551Jason Monk @Override 2729429513cc3ea6e58e330865bd621b57cb3477551Jason Monk public boolean isSecure() { 2739429513cc3ea6e58e330865bd621b57cb3477551Jason Monk KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor(); 2749429513cc3ea6e58e330865bd621b57cb3477551Jason Monk return keyguardMonitor.isSecure() && keyguardMonitor.isShowing(); 2759429513cc3ea6e58e330865bd621b57cb3477551Jason Monk } 2769429513cc3ea6e58e330865bd621b57cb3477551Jason Monk 277d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private CustomTile getTileForComponent(ComponentName component) { 278fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk synchronized (mServices) { 279fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk return mTiles.get(component); 280fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 281d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 282d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk 283fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() { 284fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk @Override 285fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk public void onReceive(Context context, Intent intent) { 286fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk if (TileService.ACTION_REQUEST_LISTENING.equals(intent.getAction())) { 287fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk requestListening( 288fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk (ComponentName) intent.getParcelableExtra(TileService.EXTRA_COMPONENT)); 289fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 290fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk } 291fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk }; 292fe8f6826ce3c2beeb1fce54c67978ce69f849407Jason Monk 293d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk private static final Comparator<TileServiceManager> SERVICE_SORT = 294d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk new Comparator<TileServiceManager>() { 295d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk @Override 296d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk public int compare(TileServiceManager left, TileServiceManager right) { 297d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk return -Integer.compare(left.getBindPriority(), right.getBindPriority()); 298d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk } 299d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk }; 300d5a204f16e7c71ffdbc6c8307a4134dcc1efd60dJason Monk} 301