IntentTile.java revision 457a21cdeac04565a0c40ad8c43a928c1182ddd1
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 48bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private IntentTile(Host host, String action) { 49bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super(host); 50bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.registerReceiver(mReceiver, new IntentFilter(action)); 51bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 52bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 53bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 54bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleDestroy() { 55bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super.handleDestroy(); 56bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.unregisterReceiver(mReceiver); 57bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 58bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 59bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public static QSTile<?> create(Host host, String spec) { 60bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) { 61bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock throw new IllegalArgumentException("Bad intent tile spec: " + spec); 62bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 63bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final String action = spec.substring(PREFIX.length(), spec.length() - 1); 64bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (action.isEmpty()) { 65bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock throw new IllegalArgumentException("Empty intent tile spec action"); 66bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 67bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock return new IntentTile(host, action); 68bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 69bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 70bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 71bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public void setListening(boolean listening) { 72bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 73bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 74bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 75bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected State newTileState() { 76bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock return new State(); 77bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 78bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 79bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 80bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleUserSwitch(int newUserId) { 81bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock super.handleUserSwitch(newUserId); 82bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mCurrentUserId = newUserId; 83bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 84bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 85bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 86bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleClick() { 87457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren super.handleClick(); 88c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock sendIntent("click", mOnClick, mOnClickUri); 89c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } 90c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock 91c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock @Override 92c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock protected void handleLongClick() { 93c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock sendIntent("long-click", mOnLongClick, mOnLongClickUri); 94c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } 95c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock 96c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock private void sendIntent(String type, PendingIntent pi, String uri) { 97bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock try { 98c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock if (pi != null) { 99c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock pi.send(); 100c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } else if (uri != null) { 101c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME); 102bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); 103bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 104bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } catch (Throwable t) { 105c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock Log.w(TAG, "Error sending " + type + " intent", t); 106bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 107bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 108bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 109bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 110bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock protected void handleUpdateState(State state, Object arg) { 111bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (!(arg instanceof Intent)) return; 112bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final Intent intent = (Intent) arg; 113bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.visible = intent.getBooleanExtra("visible", true); 114bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.contentDescription = intent.getStringExtra("contentDescription"); 115bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.label = intent.getStringExtra("label"); 116bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock state.icon = null; 117bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap"); 118bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (iconBitmap != null) { 119bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock try { 1202d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = new BytesIcon(iconBitmap); 121bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } catch (Throwable t) { 122bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t); 123bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 124bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } else { 125bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final int iconId = intent.getIntExtra("iconId", 0); 126bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (iconId != 0) { 127bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final String iconPackage = intent.getStringExtra("iconPackage"); 128bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (!TextUtils.isEmpty(iconPackage)) { 1292d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = new PackageDrawableIcon(iconPackage, iconId); 130bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } else { 1312d695813b44690ca146f95939acb00f0c14dac29John Spurlock state.icon = ResourceIcon.get(iconId); 132bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 133bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 134bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 135bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mOnClick = intent.getParcelableExtra("onClick"); 136bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mOnClickUri = intent.getStringExtra("onClickUri"); 137c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock mOnLongClick = intent.getParcelableExtra("onLongClick"); 138c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock mOnLongClickUri = intent.getStringExtra("onLongClickUri"); 139457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren mIntentPackage = intent.getStringExtra("package"); 140457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren } 141457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren 142457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren @Override 143457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren public int getMetricsCategory() { 144457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren return MetricsLogger.QS_INTENT; 145457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren } 146457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren 147457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren @Override 148457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren protected String getMetricsPackage() { 149457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren return mIntentPackage == null ? "" : mIntentPackage; 150bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 151bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 152bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 153bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock @Override 154bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public void onReceive(Context context, Intent intent) { 155bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock refreshState(intent); 156bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 157bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock }; 1582d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1592d695813b44690ca146f95939acb00f0c14dac29John Spurlock private static class BytesIcon extends Icon { 1602d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final byte[] mBytes; 1612d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1622d695813b44690ca146f95939acb00f0c14dac29John Spurlock public BytesIcon(byte[] bytes) { 1632d695813b44690ca146f95939acb00f0c14dac29John Spurlock mBytes = bytes; 1642d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1652d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1662d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1672d695813b44690ca146f95939acb00f0c14dac29John Spurlock public Drawable getDrawable(Context context) { 1682d695813b44690ca146f95939acb00f0c14dac29John Spurlock final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length); 1692d695813b44690ca146f95939acb00f0c14dac29John Spurlock return new BitmapDrawable(context.getResources(), b); 1702d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1712d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1722d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1732d695813b44690ca146f95939acb00f0c14dac29John Spurlock public boolean equals(Object o) { 1742d695813b44690ca146f95939acb00f0c14dac29John Spurlock return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes); 1752d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1762d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1772d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1782d695813b44690ca146f95939acb00f0c14dac29John Spurlock public String toString() { 1792d695813b44690ca146f95939acb00f0c14dac29John Spurlock return String.format("BytesIcon[len=%s]", mBytes.length); 1802d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1812d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1822d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1832d695813b44690ca146f95939acb00f0c14dac29John Spurlock private class PackageDrawableIcon extends Icon { 1842d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final String mPackage; 1852d695813b44690ca146f95939acb00f0c14dac29John Spurlock private final int mResId; 1862d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1872d695813b44690ca146f95939acb00f0c14dac29John Spurlock public PackageDrawableIcon(String pkg, int resId) { 1882d695813b44690ca146f95939acb00f0c14dac29John Spurlock mPackage = pkg; 1892d695813b44690ca146f95939acb00f0c14dac29John Spurlock mResId = resId; 1902d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1912d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1922d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 1932d695813b44690ca146f95939acb00f0c14dac29John Spurlock public boolean equals(Object o) { 1942d695813b44690ca146f95939acb00f0c14dac29John Spurlock if (!(o instanceof PackageDrawableIcon)) return false; 1952d695813b44690ca146f95939acb00f0c14dac29John Spurlock final PackageDrawableIcon other = (PackageDrawableIcon) o; 1962d695813b44690ca146f95939acb00f0c14dac29John Spurlock return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId; 1972d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 1982d695813b44690ca146f95939acb00f0c14dac29John Spurlock 1992d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 2002d695813b44690ca146f95939acb00f0c14dac29John Spurlock public Drawable getDrawable(Context context) { 2012d695813b44690ca146f95939acb00f0c14dac29John Spurlock try { 2022d695813b44690ca146f95939acb00f0c14dac29John Spurlock return context.createPackageContext(mPackage, 0).getDrawable(mResId); 2032d695813b44690ca146f95939acb00f0c14dac29John Spurlock } catch (Throwable t) { 2042d695813b44690ca146f95939acb00f0c14dac29John Spurlock Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t); 2052d695813b44690ca146f95939acb00f0c14dac29John Spurlock return null; 2062d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2072d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2082d695813b44690ca146f95939acb00f0c14dac29John Spurlock 2092d695813b44690ca146f95939acb00f0c14dac29John Spurlock @Override 2102d695813b44690ca146f95939acb00f0c14dac29John Spurlock public String toString() { 2112d695813b44690ca146f95939acb00f0c14dac29John Spurlock return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId); 2122d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 2132d695813b44690ca146f95939acb00f0c14dac29John Spurlock } 214bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock} 215