IntentTile.java revision 76c67aa361f65dfb2f5e03d06cc1ccebce9cecd9
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;
33f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent;
34bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport com.android.systemui.qs.QSTile;
35bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
362d695813b44690ca146f95939acb00f0c14dac29John Spurlockimport java.util.Arrays;
372d695813b44690ca146f95939acb00f0c14dac29John Spurlockimport java.util.Objects;
382d695813b44690ca146f95939acb00f0c14dac29John Spurlock
39bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockpublic class IntentTile extends QSTile<QSTile.State> {
40bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    public static final String PREFIX = "intent(";
41bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
42bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    private PendingIntent mOnClick;
43bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    private String mOnClickUri;
44c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    private PendingIntent mOnLongClick;
45c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    private String mOnLongClickUri;
46bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    private int mCurrentUserId;
47457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren    private String mIntentPackage;
48bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
49878c093336b324962f1b659aa29c79caed75ef2fJason Monk    private Intent mLastIntent;
50878c093336b324962f1b659aa29c79caed75ef2fJason Monk
51bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    private IntentTile(Host host, String action) {
52bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        super(host);
53bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mContext.registerReceiver(mReceiver, new IntentFilter(action));
54bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
55bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
56bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
57bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    protected void handleDestroy() {
58bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        super.handleDestroy();
59bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mContext.unregisterReceiver(mReceiver);
60bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
61bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
62bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    public static QSTile<?> create(Host host, String spec) {
63bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
64bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            throw new IllegalArgumentException("Bad intent tile spec: " + spec);
65bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        }
66bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        final String action = spec.substring(PREFIX.length(), spec.length() - 1);
67bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        if (action.isEmpty()) {
68bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            throw new IllegalArgumentException("Empty intent tile spec action");
69bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        }
70bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        return new IntentTile(host, action);
71bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
72bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
73bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
74bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    public void setListening(boolean listening) {
75bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
76bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
77bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
7862b63a02d7ca630e3ad39991ea6550cab57e5d22Jason Monk    public State newTileState() {
79bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        return new State();
80bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
81bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
82bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
83bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    protected void handleUserSwitch(int newUserId) {
84bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        super.handleUserSwitch(newUserId);
85bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mCurrentUserId = newUserId;
86bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
87bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
88bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
89bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    protected void handleClick() {
909e7283f6a31bc2beb75c84c6173968a46582c563Chris Wren        MetricsLogger.action(mContext, getMetricsCategory(), mIntentPackage);
91c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock        sendIntent("click", mOnClick, mOnClickUri);
92c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    }
93c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock
94c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    @Override
9576c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk    public Intent getLongClickIntent() {
9676c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk        return null;
9776c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk    }
9876c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk
9976c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk    @Override
100c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    protected void handleLongClick() {
101c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock        sendIntent("long-click", mOnLongClick, mOnLongClickUri);
102c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    }
103c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock
104c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock    private void sendIntent(String type, PendingIntent pi, String uri) {
105bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        try {
106c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock            if (pi != null) {
107ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk                if (pi.isActivity()) {
10862692b22fbb6146613635abea225f4049dae4873Adrian Roos                    getHost().startActivityDismissingKeyguard(pi);
109ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk                } else {
110ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk                    pi.send();
111ee43cdfa43b09a79e66d81f6673a79bc26427343Jason Monk                }
112c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock            } else if (uri != null) {
113c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock                final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
114bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
115bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            }
116bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        } catch (Throwable t) {
117c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock            Log.w(TAG, "Error sending " + type + " intent", t);
118bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        }
119bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
120bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
121bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
122bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    protected void handleUpdateState(State state, Object arg) {
123878c093336b324962f1b659aa29c79caed75ef2fJason Monk        Intent intent = (Intent) arg;
124878c093336b324962f1b659aa29c79caed75ef2fJason Monk        if (intent == null) {
125878c093336b324962f1b659aa29c79caed75ef2fJason Monk            if (mLastIntent == null) {
126878c093336b324962f1b659aa29c79caed75ef2fJason Monk                return;
127878c093336b324962f1b659aa29c79caed75ef2fJason Monk            }
128878c093336b324962f1b659aa29c79caed75ef2fJason Monk            // No intent but need to refresh state, just use the last one.
129878c093336b324962f1b659aa29c79caed75ef2fJason Monk            intent = mLastIntent;
130878c093336b324962f1b659aa29c79caed75ef2fJason Monk        }
131878c093336b324962f1b659aa29c79caed75ef2fJason Monk        // Save the last one in case we need it later.
132878c093336b324962f1b659aa29c79caed75ef2fJason Monk        mLastIntent = intent;
133bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        state.contentDescription = intent.getStringExtra("contentDescription");
134bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        state.label = intent.getStringExtra("label");
135bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        state.icon = null;
136bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
137bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        if (iconBitmap != null) {
138bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            try {
1392d695813b44690ca146f95939acb00f0c14dac29John Spurlock                state.icon = new BytesIcon(iconBitmap);
140bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            } catch (Throwable t) {
141bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
142bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            }
143bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        } else {
144bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            final int iconId = intent.getIntExtra("iconId", 0);
145bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            if (iconId != 0) {
146bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                final String iconPackage = intent.getStringExtra("iconPackage");
147bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                if (!TextUtils.isEmpty(iconPackage)) {
1482d695813b44690ca146f95939acb00f0c14dac29John Spurlock                    state.icon = new PackageDrawableIcon(iconPackage, iconId);
149bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                } else {
1502d695813b44690ca146f95939acb00f0c14dac29John Spurlock                    state.icon = ResourceIcon.get(iconId);
151bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock                }
152bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            }
153bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        }
154bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mOnClick = intent.getParcelableExtra("onClick");
155bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mOnClickUri = intent.getStringExtra("onClickUri");
156c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock        mOnLongClick = intent.getParcelableExtra("onLongClick");
157c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock        mOnLongClickUri = intent.getStringExtra("onLongClickUri");
158457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        mIntentPackage = intent.getStringExtra("package");
1599e7283f6a31bc2beb75c84c6173968a46582c563Chris Wren        mIntentPackage = mIntentPackage == null ? "" : mIntentPackage;
160457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren    }
161457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren
162457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren    @Override
163457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren    public int getMetricsCategory() {
164f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren        return MetricsEvent.QS_INTENT;
165457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren    }
166457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren
167bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
168bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        @Override
169bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        public void onReceive(Context context, Intent intent) {
170bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock            refreshState(intent);
171bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        }
172bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    };
1732d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1742d695813b44690ca146f95939acb00f0c14dac29John Spurlock    private static class BytesIcon extends Icon {
1752d695813b44690ca146f95939acb00f0c14dac29John Spurlock        private final byte[] mBytes;
1762d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1772d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public BytesIcon(byte[] bytes) {
1782d695813b44690ca146f95939acb00f0c14dac29John Spurlock            mBytes = bytes;
1792d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
1802d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1812d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
1822d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public Drawable getDrawable(Context context) {
1832d695813b44690ca146f95939acb00f0c14dac29John Spurlock            final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
1842d695813b44690ca146f95939acb00f0c14dac29John Spurlock            return new BitmapDrawable(context.getResources(), b);
1852d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
1862d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1872d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
1882d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public boolean equals(Object o) {
1892d695813b44690ca146f95939acb00f0c14dac29John Spurlock            return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
1902d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
1912d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1922d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
1932d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public String toString() {
1942d695813b44690ca146f95939acb00f0c14dac29John Spurlock            return String.format("BytesIcon[len=%s]", mBytes.length);
1952d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
1962d695813b44690ca146f95939acb00f0c14dac29John Spurlock    }
1972d695813b44690ca146f95939acb00f0c14dac29John Spurlock
1982d695813b44690ca146f95939acb00f0c14dac29John Spurlock    private class PackageDrawableIcon extends Icon {
1992d695813b44690ca146f95939acb00f0c14dac29John Spurlock        private final String mPackage;
2002d695813b44690ca146f95939acb00f0c14dac29John Spurlock        private final int mResId;
2012d695813b44690ca146f95939acb00f0c14dac29John Spurlock
2022d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public PackageDrawableIcon(String pkg, int resId) {
2032d695813b44690ca146f95939acb00f0c14dac29John Spurlock            mPackage = pkg;
2042d695813b44690ca146f95939acb00f0c14dac29John Spurlock            mResId = resId;
2052d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
2062d695813b44690ca146f95939acb00f0c14dac29John Spurlock
2072d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
2082d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public boolean equals(Object o) {
2092d695813b44690ca146f95939acb00f0c14dac29John Spurlock            if (!(o instanceof PackageDrawableIcon)) return false;
2102d695813b44690ca146f95939acb00f0c14dac29John Spurlock            final PackageDrawableIcon other = (PackageDrawableIcon) o;
2112d695813b44690ca146f95939acb00f0c14dac29John Spurlock            return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
2122d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
2132d695813b44690ca146f95939acb00f0c14dac29John Spurlock
2142d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
2152d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public Drawable getDrawable(Context context) {
2162d695813b44690ca146f95939acb00f0c14dac29John Spurlock            try {
2172d695813b44690ca146f95939acb00f0c14dac29John Spurlock                return context.createPackageContext(mPackage, 0).getDrawable(mResId);
2182d695813b44690ca146f95939acb00f0c14dac29John Spurlock            } catch (Throwable t) {
2192d695813b44690ca146f95939acb00f0c14dac29John Spurlock                Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
2202d695813b44690ca146f95939acb00f0c14dac29John Spurlock                return null;
2212d695813b44690ca146f95939acb00f0c14dac29John Spurlock            }
2222d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
2232d695813b44690ca146f95939acb00f0c14dac29John Spurlock
2242d695813b44690ca146f95939acb00f0c14dac29John Spurlock        @Override
2252d695813b44690ca146f95939acb00f0c14dac29John Spurlock        public String toString() {
2262d695813b44690ca146f95939acb00f0c14dac29John Spurlock            return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
2272d695813b44690ca146f95939acb00f0c14dac29John Spurlock        }
2282d695813b44690ca146f95939acb00f0c14dac29John Spurlock    }
229bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock}
230