EasProvision.java revision a09e6cc2e8fca144de4d0b69f129b177f4a3219b
1328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu/*
2328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Copyright (C) 2013 The Android Open Source Project
3328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
4328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Licensed under the Apache License, Version 2.0 (the "License");
5328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * you may not use this file except in compliance with the License.
6328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * You may obtain a copy of the License at
7328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
8328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *      http://www.apache.org/licenses/LICENSE-2.0
9328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
10328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Unless required by applicable law or agreed to in writing, software
11328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * distributed under the License is distributed on an "AS IS" BASIS,
12328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * See the License for the specific language governing permissions and
14328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * limitations under the License.
15328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu */
16328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
17328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hupackage com.android.exchange.eas;
18328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
191df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Huimport android.content.Context;
20328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport android.content.SyncResult;
21a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Leeimport android.os.Bundle;
22a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Leeimport android.telephony.TelephonyManager;
23328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
24a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Leeimport com.android.emailcommon.provider.EmailContent;
25328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.emailcommon.provider.Policy;
26328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.emailcommon.service.PolicyServiceProxy;
27328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.Eas;
28328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.EasResponse;
29328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.ProvisionParser;
30328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.Serializer;
31328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.Tags;
321df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Huimport com.android.exchange.service.EasServerConnection;
33328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.mail.utils.LogUtils;
34328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
35328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport org.apache.http.HttpEntity;
36328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
37328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport java.io.IOException;
38328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
39328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu/**
40328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Implements the EAS Provision protocol.
41328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
42328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Provisioning actually consists of two server interactions:
43328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * 1) Ask the server for the required policies.
44328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * 2) Acknowledge our disposition for enforcing those policies.
45328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
46328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * The structure of the requests and response are essentially the same for both, so we use the
47328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * same code and vary slightly based on which one we're doing. Also, provisioning responses can tell
48328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * us to wipe the device, so we need to handle that too.
49328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * TODO: Make it possible to ack separately, possibly by splitting into separate operations.
50328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * See http://msdn.microsoft.com/en-us/library/ee203567(v=exchg.80).aspx for more details.
51328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu */
52328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hupublic class EasProvision extends EasOperation {
53328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
54110837ebff288a75f9bda067c38e2c46797d99b5Alon Albert    private static final String LOG_TAG = Eas.LOG_TAG;
55328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
56328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The policy type for versions of EAS prior to 2007. */
57be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu    public static final String EAS_2_POLICY_TYPE = "MS-WAP-Provisioning-XML";
58328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The policy type for versions of EAS starting with 2007. */
59be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu    public static final String EAS_12_POLICY_TYPE = "MS-EAS-Provisioning-WBXML";
60328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
61328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The EAS protocol Provision status for "we implement all of the policies" */
62a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    static final String PROVISION_STATUS_OK = "1";
63328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The EAS protocol Provision status meaning "we partially implement the policies" */
64a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    static final String PROVISION_STATUS_PARTIAL = "2";
65328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
66328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the initial request. */
67a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    static final int PHASE_INITIAL = 0;
68328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the acknowledgement request. */
69a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    static final int PHASE_ACKNOWLEDGE = 1;
70328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the acknowledgement for a wipe. */
71a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    static final int PHASE_WIPE = 2;
72328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
73328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
74328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * This operation doesn't use public result codes because ultimately the operation answers
75328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * a yes/no question. These result codes are used internally only to communicate from
76328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * {@link #handleResponse}.
77328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
78328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
79328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server's policy can be fully supported. */
80328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_POLICY_SUPPORTED = 1;
81328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server's policy cannot be fully supported. */
82328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_POLICY_UNSUPPORTED = 2;
83328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server sent a remote wipe directive. */
84328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_REMOTE_WIPE = 3;
85328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
86328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private Policy mPolicy;
87328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private String mPolicyKey;
88328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private String mStatus;
89328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
90328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
91328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Because this operation supports variants of the request and parsing, and {@link EasOperation}
92328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * has no way to communicate this into {@link #performOperation}, we use this member variable
93328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * to vary how {@link #getRequestEntity} and {@link #handleResponse} work.
94328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
95328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int mPhase;
96328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
971df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    // TODO: Temporary until EasSyncHandler converts to EasOperation.
981df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    public EasProvision(final Context context, final long accountId,
991df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu            final EasServerConnection connection) {
1001df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        super(context, accountId, connection);
1011df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPolicy = null;
1021df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPolicyKey = null;
1031df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mStatus = null;
1041df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPhase = 0;
1051df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    }
1061df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu
107b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public EasProvision(final EasOperation parentOperation) {
108b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        super(parentOperation);
109328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicy = null;
110328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicyKey = null;
111328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mStatus = null;
112328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = 0;
113328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
114328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
115328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int performInitialRequest(final SyncResult syncResult) {
116328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_INITIAL;
117328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return performOperation(syncResult);
118328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
119328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
120328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private void performAckRequestForWipe(final SyncResult syncResult) {
121328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_WIPE;
122328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        performOperation(syncResult);
123328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
124328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
125328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int performAckRequest(final SyncResult syncResult, final boolean isPartial) {
126328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_ACKNOWLEDGE;
127328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mStatus = isPartial ? PROVISION_STATUS_PARTIAL : PROVISION_STATUS_OK;
128328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return performOperation(syncResult);
129328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
130328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
131328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
132328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Make the provisioning calls to determine if we can handle the required policy.
133b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @return The {@link Policy} if we support it, or null otherwise.
134328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
135b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public final Policy test() {
136328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        int result = performInitialRequest(null);
137328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result == RESULT_POLICY_UNSUPPORTED) {
138328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            // Check if the server will permit partial policies.
139328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            result = performAckRequest(null, true);
140328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
141b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        if (result == RESULT_POLICY_SUPPORTED) {
142be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            // The server is ok with us not supporting everything, so clear the unsupported ones.
143be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            mPolicy.mProtocolPoliciesUnsupported = null;
144b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        }
145be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        return (result == RESULT_POLICY_SUPPORTED || result == RESULT_POLICY_UNSUPPORTED)
146be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu                ? mPolicy : null;
147328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
148328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
149328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
150328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Get the required policy from the server and enforce it.
151328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @param syncResult The {@link SyncResult}, if anym for this operation.
152328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @param accountId The id for the account for this request.
153328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @return Whether we succeeded in provisioning this account.
154328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
155328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    public final boolean provision(final SyncResult syncResult, final long accountId) {
156328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final int result = performInitialRequest(syncResult);
157328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
158328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result < 0) {
159328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
160328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
161328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
162328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result == RESULT_REMOTE_WIPE) {
163328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            performAckRequestForWipe(syncResult);
164328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            LogUtils.i(LOG_TAG, "Executing remote wipe");
165328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            PolicyServiceProxy.remoteWipe(mContext);
166328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
167328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
168328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
169328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Apply the policies (that we support) with the temporary key.
170328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicy.mProtocolPoliciesUnsupported = null;
171328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, null);
172328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (!PolicyServiceProxy.isActive(mContext, mPolicy)) {
173328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
174328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
175328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
176328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Acknowledge to the server and make sure all's well.
177328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (performAckRequest(syncResult, result == RESULT_POLICY_UNSUPPORTED) ==
178328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                RESULT_POLICY_UNSUPPORTED) {
179328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
180328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
181328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
182328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Write the final policy key to the Account.
183328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, mPolicyKey);
184be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu
185be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // For 12.1 and 14.0, after provisioning we need to also send the device information via
186be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // the Settings command.
187be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // See the comments for EasSettings for more details.
188be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        final double version = getProtocolVersion();
189be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        if (version == Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE
190be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu                || version == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
191be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            final EasSettings settingsOperation = new EasSettings(this);
192be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            if (!settingsOperation.sendDeviceInformation(syncResult)) {
1932e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // TODO: Do something more useful when the settings command fails.
1942e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // The consequence here is that the server will not have device info.
1952e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // However, this is NOT a provisioning failure.
196be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            }
197be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        }
198be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu
199328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return true;
200328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
201328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
202328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
203328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected String getCommand() {
204328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return "Provision";
205328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
206328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
207a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    /**
208a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * Add the device information to the current request.
209a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param context The {@link Context} for the current device.
210a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param userAgent The user agent string that our connection uses.
211a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param policyKey EAS specific tag for Provision requests.
212a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param policyType EAS specific tag for Provision requests.
213a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param status The status value that we are sending to the server in our request.
214a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param phase The phase of the provisioning process this requests is built for.
215a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @param protocolVersion The version of the EAS protocol that we should speak.
216a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @return The {@link Serializer} containing the payload for this request.
217a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     */
218a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    protected static Serializer generateRequestEntitySerializer(
219a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            final Context context, final String userAgent, final String policyKey,
220a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            final String policyType, final String status, final int phase,
221a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            final double protocolVersion) throws IOException {
222328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final Serializer s = new Serializer();
223328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.start(Tags.PROVISION_PROVISION);
224328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
225328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // When requesting the policy in 14.1, we also need to send device information.
226a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        if (phase == PHASE_INITIAL &&
227a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee                protocolVersion >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
228a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            // The "inner" version of this function is being used because it is
229a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            // re-entrant and can be unit tested easier.  Until we are unit testing
230a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            // everything, the other version of this function still lives so that
231a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            // we are disrupting as little code as possible for now.
232a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            expandedAddDeviceInformationToSerializer(s, context, userAgent);
233328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
234a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        if (phase == PHASE_WIPE) {
235328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.start(Tags.PROVISION_REMOTE_WIPE);
236328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.data(Tags.PROVISION_STATUS, PROVISION_STATUS_OK);
237a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            s.end(); // PROVISION_REMOTE_WIPE
238a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        } else {
239a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            s.start(Tags.PROVISION_POLICIES);
240a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            s.start(Tags.PROVISION_POLICY);
241a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            s.data(Tags.PROVISION_POLICY_TYPE, policyType);
242a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            // When acknowledging a policy, we tell the server whether we applied the policy.
243a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            if (phase == PHASE_ACKNOWLEDGE) {
244a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee                s.data(Tags.PROVISION_POLICY_KEY, policyKey);
245a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee                s.data(Tags.PROVISION_STATUS, status);
246a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            }
247a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee            s.end().end(); // PROVISION_POLICY, PROVISION_POLICIES,
248328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
249a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        s.end().done(); // PROVISION_PROVISION
250a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        return s;
251a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    }
252328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
253a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    /**
254a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * Generates a request entity based on the type of request and our current context.
255a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     * @return The {@link HttpEntity} that was generated for this request.
256a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee     */
257a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    @Override
258a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee    protected HttpEntity getRequestEntity() throws IOException {
259a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        final String policyType = getPolicyType();
260a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        final String userAgent = getUserAgent();
261a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        final double protocolVersion = getProtocolVersion();
262a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee        final Serializer s = generateRequestEntitySerializer(mContext, userAgent, mPolicyKey,
263a09e6cc2e8fca144de4d0b69f129b177f4a3219bAnthony Lee                policyType, mStatus, mPhase, protocolVersion);
264328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return makeEntity(s);
265328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
266328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
267328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
268328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected int handleResponse(final EasResponse response, final SyncResult syncResult)
269328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            throws IOException {
270328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final ProvisionParser pp = new ProvisionParser(mContext, response.getInputStream());
271328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If this is the response for a remote wipe ack, it doesn't have anything useful in it.
272328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Just go ahead and return now.
273328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_WIPE) {
274328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return RESULT_REMOTE_WIPE;
275328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
276328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
277328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (!pp.parse()) {
278328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            throw new IOException("Error while parsing response");
279328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
280328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
281328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // What we care about in the response depends on what phase we're in.
282328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_INITIAL) {
283328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            if (pp.getRemoteWipe()) {
284328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                return RESULT_REMOTE_WIPE;
285328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            }
286328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicy = pp.getPolicy();
287328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicyKey = pp.getSecuritySyncKey();
288328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
289328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return (pp.hasSupportablePolicySet()
290328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                    ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
291328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
292328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
293328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_ACKNOWLEDGE) {
294328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicyKey = pp.getSecuritySyncKey();
295328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return (mPolicyKey != null ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
296328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
297328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
298328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Note: this should be unreachable, but the compiler doesn't know it.
299328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If we somehow get here, act like we can't do anything.
300328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return RESULT_POLICY_UNSUPPORTED;
301328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
302328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
303328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
304328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected boolean handleProvisionError(final SyncResult syncResult, final long accountId) {
305328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If we get a provisioning error while doing provisioning, we should not recurse.
306328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return false;
307328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
308328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
309328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
310328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @return The policy type for this connection.
311328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
312328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private final String getPolicyType() {
313328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) ?
314328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                EAS_12_POLICY_TYPE : EAS_2_POLICY_TYPE;
315328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
316328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu}
317