IntentTile.java revision 62692b22fbb6146613635abea225f4049dae4873
1bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock/* 2bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * Copyright (C) 2014 The Android Open Source Project 3bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * 4bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 5bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * you may not use this file except in compliance with the License. 6bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * You may obtain a copy of the License at 7bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * 8bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 9bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * 10bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * Unless required by applicable law or agreed to in writing, software 11bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 12bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * See the License for the specific language governing permissions and 14bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock * limitations under the License. 15bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock */ 16bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 17bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockpackage com.android.systemui.qs.tiles; 18bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 19bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.app.PendingIntent; 20bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.content.BroadcastReceiver; 21bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.content.Context; 22bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.content.Intent; 23bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.content.IntentFilter; 24bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.graphics.Bitmap; 25bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.graphics.BitmapFactory; 26bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.graphics.drawable.BitmapDrawable; 27bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.graphics.drawable.Drawable; 28bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.os.UserHandle; 29bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.text.TextUtils; 30bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.util.Log; 31bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 32457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wrenimport com.android.internal.logging.MetricsLogger; 33bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport com.android.systemui.qs.QSTile; 34bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 352d695813b44690ca146f95939acb00f0c14dac29John Spurlockimport java.util.Arrays; 362d695813b44690ca146f95939acb00f0c14dac29John Spurlockimport java.util.Objects; 372d695813b44690ca146f95939acb00f0c14dac29John Spurlock 38bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockpublic class IntentTile extends QSTile<QSTile.State> { 39bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public static final String PREFIX = "intent("; 40bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 41bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private PendingIntent mOnClick; 42bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private String mOnClickUri; 43c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock private PendingIntent mOnLongClick; 44c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock private String mOnLongClickUri; 45bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private int mCurrentUserId; 46457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren private String mIntentPackage; 47bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 48878c093336b324962f1b659aa29c79caed75ef2fJason Monk private Intent mLastIntent; 49878c093336b324962f1b659aa29c79caed75ef2fJason Monk 50bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private IntentTile(Host host, String action) { 51bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super(host); 52bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.registerReceiver(mReceiver, new IntentFilter(action)); 53bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 54bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 55bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 56bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleDestroy() { 57bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super.handleDestroy(); 58bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.unregisterReceiver(mReceiver); 59bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 60bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 61bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public static QSTile<?> create(Host host, String spec) { 62bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) { 63bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock throw new IllegalArgumentException("Bad intent tile spec: " + spec); 64bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 65bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final String action = spec.substring(PREFIX.length(), spec.length() - 1); 66bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (action.isEmpty()) { 67bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock throw new IllegalArgumentException("Empty intent tile spec action"); 68bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 69bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock return new IntentTile(host, action); 70bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 71bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 72bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 73bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public void setListening(boolean listening) { 74bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 75bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 76bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 77bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected State newTileState() { 78bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock return new State(); 79bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 80bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 81bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 82bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleUserSwitch(int newUserId) { 83bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super.handleUserSwitch(newUserId); 84bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mCurrentUserId = newUserId; 85bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 86bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 87bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 88bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleClick() { 899e7283f6a31bc2beb75c84c6173968a46582c563Chris Wren MetricsLogger.action(mContext, getMetricsCategory(), mIntentPackage); 90c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock sendIntent("click", mOnClick, mOnClickUri); 91c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } 92c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock 93c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock @Override 94c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock protected void handleLongClick() { 95c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock sendIntent("long-click", mOnLongClick, mOnLongClickUri); 96c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } 97c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock 98c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock private void sendIntent(String type, PendingIntent pi, String uri) { 99bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock try { 100c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock if (pi != null) { 101ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk if (pi.isActivity()) { 10262692b22fbb6146613635abea225f4049dae4873Adrian Roos getHost().startActivityDismissingKeyguard(pi); 103ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk } else { 104ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk pi.send(); 105ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk } 106c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } else if (uri != null) { 107c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME); 108bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); 109bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 110bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } catch (Throwable t) { 111c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock Log.w(TAG, "Error sending " + type + " intent", t); 112bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 113bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 114bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 115bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 116bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleUpdateState(State state, Object arg) { 117878c093336b324962f1b659aa29c79caed75ef2fJason Monk Intent intent = (Intent) arg; 118878c093336b324962f1b659aa29c79caed75ef2fJason Monk if (intent == null) { 119878c093336b324962f1b659aa29c79caed75ef2fJason Monk if (mLastIntent == null) { 120878c093336b324962f1b659aa29c79caed75ef2fJason Monk return; 121878c093336b324962f1b659aa29c79caed75ef2fJason Monk } 122878c093336b324962f1b659aa29c79caed75ef2fJason Monk // No intent but need to refresh state, just use the last one. 123878c093336b324962f1b659aa29c79caed75ef2fJason Monk intent = mLastIntent; 124878c093336b324962f1b659aa29c79caed75ef2fJason Monk } 125878c093336b324962f1b659aa29c79caed75ef2fJason Monk // Save the last one in case we need it later. 126878c093336b324962f1b659aa29c79caed75ef2fJason Monk mLastIntent = intent; 127bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.visible = intent.getBooleanExtra("visible", true); 128bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.contentDescription = intent.getStringExtra("contentDescription"); 129bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.label = intent.getStringExtra("label"); 130bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.icon = null; 131bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap"); 132bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (iconBitmap != null) { 133bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock try { 1342d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = new BytesIcon(iconBitmap); 135bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } catch (Throwable t) { 136bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t); 137bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 138bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } else { 139bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final int iconId = intent.getIntExtra("iconId", 0); 140bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (iconId != 0) { 141bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final String iconPackage = intent.getStringExtra("iconPackage"); 142bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (!TextUtils.isEmpty(iconPackage)) { 1432d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = new PackageDrawableIcon(iconPackage, iconId); 144bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } else { 1452d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = ResourceIcon.get(iconId); 146bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 147bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 148bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 149bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mOnClick = intent.getParcelableExtra("onClick"); 150bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mOnClickUri = intent.getStringExtra("onClickUri"); 151c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock mOnLongClick = intent.getParcelableExtra("onLongClick"); 152c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock mOnLongClickUri = intent.getStringExtra("onLongClickUri"); 153457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren mIntentPackage = intent.getStringExtra("package"); 1549e7283f6a31bc2beb75c84c6173968a46582c563Chris Wren mIntentPackage = mIntentPackage == null ? "" : mIntentPackage; 155457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren } 156457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren 157457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren @Override 158457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren public int getMetricsCategory() { 159457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren return MetricsLogger.QS_INTENT; 160457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren } 161457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren 162bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 163bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 164bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public void onReceive(Context context, Intent intent) { 165bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock refreshState(intent); 166bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 167bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock }; 1682d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1692d695813b44690ca146f95939acb00f0c14dac29John Spurlock private static class BytesIcon extends Icon { 1702d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final byte[] mBytes; 1712d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1722d695813b44690ca146f95939acb00f0c14dac29John Spurlock public BytesIcon(byte[] bytes) { 1732d695813b44690ca146f95939acb00f0c14dac29John Spurlock mBytes = bytes; 1742d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1752d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1762d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1772d695813b44690ca146f95939acb00f0c14dac29John Spurlock public Drawable getDrawable(Context context) { 1782d695813b44690ca146f95939acb00f0c14dac29John Spurlock final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length); 1792d695813b44690ca146f95939acb00f0c14dac29John Spurlock return new BitmapDrawable(context.getResources(), b); 1802d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1812d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1822d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1832d695813b44690ca146f95939acb00f0c14dac29John Spurlock public boolean equals(Object o) { 1842d695813b44690ca146f95939acb00f0c14dac29John Spurlock return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes); 1852d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1862d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1872d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1882d695813b44690ca146f95939acb00f0c14dac29John Spurlock public String toString() { 1892d695813b44690ca146f95939acb00f0c14dac29John Spurlock return String.format("BytesIcon[len=%s]", mBytes.length); 1902d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1912d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1922d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1932d695813b44690ca146f95939acb00f0c14dac29John Spurlock private class PackageDrawableIcon extends Icon { 1942d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final String mPackage; 1952d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final int mResId; 1962d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1972d695813b44690ca146f95939acb00f0c14dac29John Spurlock public PackageDrawableIcon(String pkg, int resId) { 1982d695813b44690ca146f95939acb00f0c14dac29John Spurlock mPackage = pkg; 1992d695813b44690ca146f95939acb00f0c14dac29John Spurlock mResId = resId; 2002d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2012d695813b44690ca146f95939acb00f0c14dac29John Spurlock 2022d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 2032d695813b44690ca146f95939acb00f0c14dac29John Spurlock public boolean equals(Object o) { 2042d695813b44690ca146f95939acb00f0c14dac29John Spurlock if (!(o instanceof PackageDrawableIcon)) return false; 2052d695813b44690ca146f95939acb00f0c14dac29John Spurlock final PackageDrawableIcon other = (PackageDrawableIcon) o; 2062d695813b44690ca146f95939acb00f0c14dac29John Spurlock return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId; 2072d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2082d695813b44690ca146f95939acb00f0c14dac29John Spurlock 2092d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 2102d695813b44690ca146f95939acb00f0c14dac29John Spurlock public Drawable getDrawable(Context context) { 2112d695813b44690ca146f95939acb00f0c14dac29John Spurlock try { 2122d695813b44690ca146f95939acb00f0c14dac29John Spurlock return context.createPackageContext(mPackage, 0).getDrawable(mResId); 2132d695813b44690ca146f95939acb00f0c14dac29John Spurlock } catch (Throwable t) { 2142d695813b44690ca146f95939acb00f0c14dac29John Spurlock Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t); 2152d695813b44690ca146f95939acb00f0c14dac29John Spurlock return null; 2162d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2172d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2182d695813b44690ca146f95939acb00f0c14dac29John Spurlock 2192d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 2202d695813b44690ca146f95939acb00f0c14dac29John Spurlock public String toString() { 2212d695813b44690ca146f95939acb00f0c14dac29John Spurlock return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId); 2222d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2232d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 224bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock} 225