OSDN Git Service

Merge "Docs only change: update build version docs." into mnc-dev
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / qs / tiles / IntentTile.java
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.systemui.qs.tiles;
18
19 import android.app.PendingIntent;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.graphics.Bitmap;
25 import android.graphics.BitmapFactory;
26 import android.graphics.drawable.BitmapDrawable;
27 import android.graphics.drawable.Drawable;
28 import android.os.UserHandle;
29 import android.text.TextUtils;
30 import android.util.Log;
31
32 import com.android.internal.logging.MetricsLogger;
33 import com.android.systemui.qs.QSTile;
34
35 import java.util.Arrays;
36 import java.util.Objects;
37
38 public class IntentTile extends QSTile<QSTile.State> {
39     public static final String PREFIX = "intent(";
40
41     private PendingIntent mOnClick;
42     private String mOnClickUri;
43     private PendingIntent mOnLongClick;
44     private String mOnLongClickUri;
45     private int mCurrentUserId;
46     private String mIntentPackage;
47
48     private Intent mLastIntent;
49
50     private IntentTile(Host host, String action) {
51         super(host);
52         mContext.registerReceiver(mReceiver, new IntentFilter(action));
53     }
54
55     @Override
56     protected void handleDestroy() {
57         super.handleDestroy();
58         mContext.unregisterReceiver(mReceiver);
59     }
60
61     public static QSTile<?> create(Host host, String spec) {
62         if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
63             throw new IllegalArgumentException("Bad intent tile spec: " + spec);
64         }
65         final String action = spec.substring(PREFIX.length(), spec.length() - 1);
66         if (action.isEmpty()) {
67             throw new IllegalArgumentException("Empty intent tile spec action");
68         }
69         return new IntentTile(host, action);
70     }
71
72     @Override
73     public void setListening(boolean listening) {
74     }
75
76     @Override
77     protected State newTileState() {
78         return new State();
79     }
80
81     @Override
82     protected void handleUserSwitch(int newUserId) {
83         super.handleUserSwitch(newUserId);
84         mCurrentUserId = newUserId;
85     }
86
87     @Override
88     protected void handleClick() {
89         MetricsLogger.action(mContext, getMetricsCategory(), mIntentPackage);
90         sendIntent("click", mOnClick, mOnClickUri);
91     }
92
93     @Override
94     protected void handleLongClick() {
95         sendIntent("long-click", mOnLongClick, mOnLongClickUri);
96     }
97
98     private void sendIntent(String type, PendingIntent pi, String uri) {
99         try {
100             if (pi != null) {
101                 if (pi.isActivity()) {
102                     getHost().startActivityDismissingKeyguard(pi);
103                 } else {
104                     pi.send();
105                 }
106             } else if (uri != null) {
107                 final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
108                 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
109             }
110         } catch (Throwable t) {
111             Log.w(TAG, "Error sending " + type + " intent", t);
112         }
113     }
114
115     @Override
116     protected void handleUpdateState(State state, Object arg) {
117         Intent intent = (Intent) arg;
118         if (intent == null) {
119             if (mLastIntent == null) {
120                 return;
121             }
122             // No intent but need to refresh state, just use the last one.
123             intent = mLastIntent;
124         }
125         // Save the last one in case we need it later.
126         mLastIntent = intent;
127         state.visible = intent.getBooleanExtra("visible", true);
128         state.contentDescription = intent.getStringExtra("contentDescription");
129         state.label = intent.getStringExtra("label");
130         state.icon = null;
131         final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
132         if (iconBitmap != null) {
133             try {
134                 state.icon = new BytesIcon(iconBitmap);
135             } catch (Throwable t) {
136                 Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
137             }
138         } else {
139             final int iconId = intent.getIntExtra("iconId", 0);
140             if (iconId != 0) {
141                 final String iconPackage = intent.getStringExtra("iconPackage");
142                 if (!TextUtils.isEmpty(iconPackage)) {
143                     state.icon = new PackageDrawableIcon(iconPackage, iconId);
144                 } else {
145                     state.icon = ResourceIcon.get(iconId);
146                 }
147             }
148         }
149         mOnClick = intent.getParcelableExtra("onClick");
150         mOnClickUri = intent.getStringExtra("onClickUri");
151         mOnLongClick = intent.getParcelableExtra("onLongClick");
152         mOnLongClickUri = intent.getStringExtra("onLongClickUri");
153         mIntentPackage = intent.getStringExtra("package");
154         mIntentPackage = mIntentPackage == null ? "" : mIntentPackage;
155     }
156
157     @Override
158     public int getMetricsCategory() {
159         return MetricsLogger.QS_INTENT;
160     }
161
162     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
163         @Override
164         public void onReceive(Context context, Intent intent) {
165             refreshState(intent);
166         }
167     };
168
169     private static class BytesIcon extends Icon {
170         private final byte[] mBytes;
171
172         public BytesIcon(byte[] bytes) {
173             mBytes = bytes;
174         }
175
176         @Override
177         public Drawable getDrawable(Context context) {
178             final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
179             return new BitmapDrawable(context.getResources(), b);
180         }
181
182         @Override
183         public boolean equals(Object o) {
184             return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
185         }
186
187         @Override
188         public String toString() {
189             return String.format("BytesIcon[len=%s]", mBytes.length);
190         }
191     }
192
193     private class PackageDrawableIcon extends Icon {
194         private final String mPackage;
195         private final int mResId;
196
197         public PackageDrawableIcon(String pkg, int resId) {
198             mPackage = pkg;
199             mResId = resId;
200         }
201
202         @Override
203         public boolean equals(Object o) {
204             if (!(o instanceof PackageDrawableIcon)) return false;
205             final PackageDrawableIcon other = (PackageDrawableIcon) o;
206             return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
207         }
208
209         @Override
210         public Drawable getDrawable(Context context) {
211             try {
212                 return context.createPackageContext(mPackage, 0).getDrawable(mResId);
213             } catch (Throwable t) {
214                 Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
215                 return null;
216             }
217         }
218
219         @Override
220         public String toString() {
221             return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
222         }
223     }
224 }