1package com.xtremelabs.robolectric.shadows;
2
3import android.app.PendingIntent;
4import android.app.PendingIntent.CanceledException;
5import android.content.Context;
6import android.content.Intent;
7import android.content.IntentSender;
8import android.content.TestIntentSender;
9import android.os.Parcel;
10
11import com.xtremelabs.robolectric.Robolectric;
12import com.xtremelabs.robolectric.internal.Implementation;
13import com.xtremelabs.robolectric.internal.Implements;
14
15/**
16 * Shadow of {@code PendingIntent} that creates and sends {@code Intent}s appropriately.
17 */
18@Implements(PendingIntent.class)
19public class ShadowPendingIntent {
20    private Intent savedIntent;
21    private Context savedContext;
22    private boolean isActivityIntent;
23    private boolean isBroadcastIntent;
24    private boolean isServiceIntent;
25    private int requestCode;
26
27    @Implementation
28    public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) {
29        return create(context, intent, true, false, false, requestCode);
30    }
31
32    @Implementation
33    public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) {
34        return create(context, intent, false, true, false, requestCode);
35    }
36
37    @Implementation
38    public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags) {
39        return create(context, intent, false, false, true, requestCode);
40    }
41
42    @Implementation
43    public void send() throws CanceledException {
44        send(savedContext, 0, savedIntent);
45    }
46
47    @Implementation
48    public void send(Context context, int code, Intent intent) throws CanceledException {
49        savedIntent.fillIn(intent, 0 );
50        if (isActivityIntent) {
51            context.startActivity(savedIntent);
52        } else if (isBroadcastIntent) {
53            context.sendBroadcast(savedIntent);
54        } else if (isServiceIntent) {
55            context.startService(savedIntent);
56        }
57    }
58
59    @Implementation
60    public IntentSender getIntentSender() {
61        TestIntentSender testIntentSender = new TestIntentSender();
62        testIntentSender.intent = savedIntent;
63        return testIntentSender;
64    }
65
66    @Implementation
67    public static void writePendingIntentOrNullToParcel(PendingIntent sender, Parcel out) {
68        if (sender == null) {
69            out.writeInt(0);
70            return;
71        }
72        sender.writeToParcel(out, 0);
73    }
74
75    @Implementation
76    public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
77        if (in.readInt() == 0) {
78            return null;
79        }
80        boolean isActivity = readBooleanFromParcel(in);
81        boolean isBroadcast = readBooleanFromParcel(in);
82        boolean isService = readBooleanFromParcel(in);
83        int requestCode = in.readInt();
84        Intent intent = null;
85        if (in.readInt() != 0) {
86            intent = new Intent();
87            intent.readFromParcel(in);
88        }
89        return create(null, intent, isActivity, isBroadcast, isService, requestCode);
90    }
91
92    @Implementation
93    public void writeToParcel(Parcel out, int flags) {
94        out.writeInt(1);
95        writeBooleanToParcel(isActivityIntent, out);
96        writeBooleanToParcel(isBroadcastIntent, out);
97        writeBooleanToParcel(isServiceIntent, out);
98        out.writeInt(requestCode);
99        if (savedIntent != null) {
100            out.writeInt(1);
101            savedIntent.writeToParcel(out, flags);
102        } else {
103            out.writeInt(0);
104        }
105    }
106
107    @Override
108    @Implementation
109    public int hashCode() {
110        final int prime = 31;
111        int result = 1;
112        result = prime * result + (isActivityIntent ? 1231 : 1237);
113        result = prime * result + (isBroadcastIntent ? 1231 : 1237);
114        result = prime * result + (isServiceIntent ? 1231 : 1237);
115        result = prime * result + requestCode;
116        result = prime * result + ((savedIntent == null) ? 0 : savedIntent.hashCode());
117        return result;
118    }
119
120    @Override
121    @Implementation
122    public boolean equals(Object obj) {
123        if (obj == null) {
124            return false;
125        }
126        if (obj instanceof PendingIntent) {
127            return shadowEquals(Robolectric.shadowOf((PendingIntent) obj));
128        }
129        return false;
130    }
131
132    private boolean shadowEquals(ShadowPendingIntent other) {
133        if (isActivityIntent != other.isActivityIntent) {
134            return false;
135        }
136        if (isBroadcastIntent != other.isBroadcastIntent) {
137            return false;
138        }
139        if (isServiceIntent != other.isServiceIntent) {
140            return false;
141        }
142        if (requestCode != other.requestCode) {
143            return false;
144        }
145        if (savedIntent == null) {
146            if (other.savedIntent != null) {
147            return false;
148            }
149        } else if (!savedIntent.equals(other.savedIntent)) {
150            return false;
151        }
152        return true;
153    }
154
155    public boolean isActivityIntent() {
156        return isActivityIntent;
157    }
158
159    public boolean isBroadcastIntent() {
160        return isBroadcastIntent;
161    }
162
163    public boolean isServiceIntent() {
164        return isServiceIntent;
165    }
166
167    public Context getSavedContext() {
168        return savedContext;
169    }
170
171    public Intent getSavedIntent() {
172        return savedIntent;
173    }
174
175    public int getRequestCode() {
176        return requestCode;
177    }
178
179    private static PendingIntent create(Context context, Intent intent, boolean isActivity, boolean isBroadcast, boolean isService, int requestCode) {
180        PendingIntent pendingIntent = Robolectric.newInstanceOf(PendingIntent.class);
181        ShadowPendingIntent shadowPendingIntent = Robolectric.shadowOf(pendingIntent);
182        shadowPendingIntent.savedIntent = intent;
183        shadowPendingIntent.isActivityIntent = isActivity;
184        shadowPendingIntent.isBroadcastIntent = isBroadcast;
185        shadowPendingIntent.isServiceIntent = isService;
186        shadowPendingIntent.savedContext = context;
187        shadowPendingIntent.requestCode = requestCode;
188        return pendingIntent;
189    }
190
191    private static void writeBooleanToParcel(boolean b, Parcel out) {
192        out.writeInt(b ? 1 : 0);
193    }
194
195    private static boolean readBooleanFromParcel(Parcel in) {
196        return in.readInt() != 0;
197    }
198}
199