EasProvision.java revision 2e8ce13ff0b47f2b0b2f06541a0c155e0727a40d
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;
21328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
22328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.emailcommon.provider.Policy;
23328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.emailcommon.service.PolicyServiceProxy;
24328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.Eas;
25328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.EasResponse;
26328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.ProvisionParser;
27328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.Serializer;
28328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.adapter.Tags;
291df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Huimport com.android.exchange.service.EasServerConnection;
30328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.mail.utils.LogUtils;
31328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
32328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport org.apache.http.HttpEntity;
33328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
34328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport java.io.IOException;
35328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
36328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu/**
37328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Implements the EAS Provision protocol.
38328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
39328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * Provisioning actually consists of two server interactions:
40328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * 1) Ask the server for the required policies.
41328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * 2) Acknowledge our disposition for enforcing those policies.
42328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu *
43328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * The structure of the requests and response are essentially the same for both, so we use the
44328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * same code and vary slightly based on which one we're doing. Also, provisioning responses can tell
45328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * us to wipe the device, so we need to handle that too.
46328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * TODO: Make it possible to ack separately, possibly by splitting into separate operations.
47328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu * See http://msdn.microsoft.com/en-us/library/ee203567(v=exchg.80).aspx for more details.
48328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu */
49328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hupublic class EasProvision extends EasOperation {
50328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
51110837ebff288a75f9bda067c38e2c46797d99b5Alon Albert    private static final String LOG_TAG = Eas.LOG_TAG;
52328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
53328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The policy type for versions of EAS prior to 2007. */
54be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu    public static final String EAS_2_POLICY_TYPE = "MS-WAP-Provisioning-XML";
55328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The policy type for versions of EAS starting with 2007. */
56be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu    public static final String EAS_12_POLICY_TYPE = "MS-EAS-Provisioning-WBXML";
57328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
58328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The EAS protocol Provision status for "we implement all of the policies" */
59328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final String PROVISION_STATUS_OK = "1";
60328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** The EAS protocol Provision status meaning "we partially implement the policies" */
61328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final String PROVISION_STATUS_PARTIAL = "2";
62328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
63328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the initial request. */
64328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int PHASE_INITIAL = 0;
65328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the acknowledgement request. */
66328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int PHASE_ACKNOWLEDGE = 1;
67328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Value for {@link #mPhase} indicating we're performing the acknowledgement for a wipe. */
68328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int PHASE_WIPE = 2;
69328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
70328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
71328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * This operation doesn't use public result codes because ultimately the operation answers
72328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * a yes/no question. These result codes are used internally only to communicate from
73328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * {@link #handleResponse}.
74328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
75328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
76328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server's policy can be fully supported. */
77328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_POLICY_SUPPORTED = 1;
78328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server's policy cannot be fully supported. */
79328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_POLICY_UNSUPPORTED = 2;
80328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /** Result code indicating the server sent a remote wipe directive. */
81328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private static final int RESULT_REMOTE_WIPE = 3;
82328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
83328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private Policy mPolicy;
84328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private String mPolicyKey;
85328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private String mStatus;
86328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
87328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
88328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Because this operation supports variants of the request and parsing, and {@link EasOperation}
89328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * has no way to communicate this into {@link #performOperation}, we use this member variable
90328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * to vary how {@link #getRequestEntity} and {@link #handleResponse} work.
91328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
92328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int mPhase;
93328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
941df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    // TODO: Temporary until EasSyncHandler converts to EasOperation.
951df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    public EasProvision(final Context context, final long accountId,
961df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu            final EasServerConnection connection) {
971df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        super(context, accountId, connection);
981df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPolicy = null;
991df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPolicyKey = null;
1001df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mStatus = null;
1011df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu        mPhase = 0;
1021df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu    }
1031df4a493b2efa34fce4bd8a70aca57203b4ed037Yu Ping Hu
104b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public EasProvision(final EasOperation parentOperation) {
105b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        super(parentOperation);
106328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicy = null;
107328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicyKey = null;
108328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mStatus = null;
109328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = 0;
110328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
111328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
112328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int performInitialRequest(final SyncResult syncResult) {
113328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_INITIAL;
114328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return performOperation(syncResult);
115328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
116328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
117328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private void performAckRequestForWipe(final SyncResult syncResult) {
118328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_WIPE;
119328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        performOperation(syncResult);
120328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
121328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
122328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private int performAckRequest(final SyncResult syncResult, final boolean isPartial) {
123328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPhase = PHASE_ACKNOWLEDGE;
124328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mStatus = isPartial ? PROVISION_STATUS_PARTIAL : PROVISION_STATUS_OK;
125328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return performOperation(syncResult);
126328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
127328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
128328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
129328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Make the provisioning calls to determine if we can handle the required policy.
130b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @return The {@link Policy} if we support it, or null otherwise.
131328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
132b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public final Policy test() {
133328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        int result = performInitialRequest(null);
134328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result == RESULT_POLICY_UNSUPPORTED) {
135328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            // Check if the server will permit partial policies.
136328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            result = performAckRequest(null, true);
137328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
138b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        if (result == RESULT_POLICY_SUPPORTED) {
139be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            // The server is ok with us not supporting everything, so clear the unsupported ones.
140be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            mPolicy.mProtocolPoliciesUnsupported = null;
141b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        }
142be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        return (result == RESULT_POLICY_SUPPORTED || result == RESULT_POLICY_UNSUPPORTED)
143be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu                ? mPolicy : null;
144328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
145328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
146328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
147328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * Get the required policy from the server and enforce it.
148328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @param syncResult The {@link SyncResult}, if anym for this operation.
149328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @param accountId The id for the account for this request.
150328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @return Whether we succeeded in provisioning this account.
151328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
152328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    public final boolean provision(final SyncResult syncResult, final long accountId) {
153328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final int result = performInitialRequest(syncResult);
154328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
155328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result < 0) {
156328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
157328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
158328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
159328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (result == RESULT_REMOTE_WIPE) {
160328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            performAckRequestForWipe(syncResult);
161328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            LogUtils.i(LOG_TAG, "Executing remote wipe");
162328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            PolicyServiceProxy.remoteWipe(mContext);
163328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
164328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
165328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
166328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Apply the policies (that we support) with the temporary key.
167328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        mPolicy.mProtocolPoliciesUnsupported = null;
168328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, null);
169328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (!PolicyServiceProxy.isActive(mContext, mPolicy)) {
170328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
171328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
172328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
173328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Acknowledge to the server and make sure all's well.
174328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (performAckRequest(syncResult, result == RESULT_POLICY_UNSUPPORTED) ==
175328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                RESULT_POLICY_UNSUPPORTED) {
176328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return false;
177328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
178328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
179328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Write the final policy key to the Account.
180328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, mPolicyKey);
181be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu
182be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // For 12.1 and 14.0, after provisioning we need to also send the device information via
183be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // the Settings command.
184be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        // See the comments for EasSettings for more details.
185be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        final double version = getProtocolVersion();
186be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        if (version == Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE
187be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu                || version == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
188be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            final EasSettings settingsOperation = new EasSettings(this);
189be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            if (!settingsOperation.sendDeviceInformation(syncResult)) {
1902e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // TODO: Do something more useful when the settings command fails.
1912e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // The consequence here is that the server will not have device info.
1922e8ce13ff0b47f2b0b2f06541a0c155e0727a40dYu Ping Hu                // However, this is NOT a provisioning failure.
193be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            }
194be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu        }
195be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu
196328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return true;
197328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
198328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
199328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
200328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected String getCommand() {
201328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return "Provision";
202328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
203328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
204328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
205328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected HttpEntity getRequestEntity() throws IOException {
206328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final Serializer s = new Serializer();
207328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.start(Tags.PROVISION_PROVISION);
208328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
209328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // When requesting the policy in 14.1, we also need to send device information.
210328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_INITIAL &&
211328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
212be22ff8b8b3aa6057de165b76da433cabad4dcfdYu Ping Hu            addDeviceInformationToSerlializer(s);
213328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
214328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.start(Tags.PROVISION_POLICIES);
215328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.start(Tags.PROVISION_POLICY);
216328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.data(Tags.PROVISION_POLICY_TYPE, getPolicyType());
217328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
218328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // When acknowledging a policy, we tell the server whether we applied the policy.
219328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_ACKNOWLEDGE) {
220328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.data(Tags.PROVISION_POLICY_KEY, mPolicyKey);
221328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.data(Tags.PROVISION_STATUS, mStatus);
222328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
223328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_WIPE) {
224328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.start(Tags.PROVISION_REMOTE_WIPE);
225328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.data(Tags.PROVISION_STATUS, PROVISION_STATUS_OK);
226328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            s.end();
227328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
228328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        s.end().end().end().done(); // PROVISION_POLICY, PROVISION_POLICIES, PROVISION_PROVISION
229328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
230328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return makeEntity(s);
231328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
232328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
233328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
234328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected int handleResponse(final EasResponse response, final SyncResult syncResult)
235328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            throws IOException {
236328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        final ProvisionParser pp = new ProvisionParser(mContext, response.getInputStream());
237328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If this is the response for a remote wipe ack, it doesn't have anything useful in it.
238328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Just go ahead and return now.
239328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_WIPE) {
240328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return RESULT_REMOTE_WIPE;
241328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
242328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
243328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (!pp.parse()) {
244328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            throw new IOException("Error while parsing response");
245328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
246328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
247328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // What we care about in the response depends on what phase we're in.
248328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_INITIAL) {
249328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            if (pp.getRemoteWipe()) {
250328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                return RESULT_REMOTE_WIPE;
251328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            }
252328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicy = pp.getPolicy();
253328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicyKey = pp.getSecuritySyncKey();
254328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
255328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return (pp.hasSupportablePolicySet()
256328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                    ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
257328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
258328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
259328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        if (mPhase == PHASE_ACKNOWLEDGE) {
260328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            mPolicyKey = pp.getSecuritySyncKey();
261328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu            return (mPolicyKey != null ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
262328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        }
263328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
264328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // Note: this should be unreachable, but the compiler doesn't know it.
265328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If we somehow get here, act like we can't do anything.
266328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return RESULT_POLICY_UNSUPPORTED;
267328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
268328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
269328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    @Override
270328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    protected boolean handleProvisionError(final SyncResult syncResult, final long accountId) {
271328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        // If we get a provisioning error while doing provisioning, we should not recurse.
272328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return false;
273328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
274328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu
275328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    /**
276328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     * @return The policy type for this connection.
277328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu     */
278328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    private final String getPolicyType() {
279328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu        return (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) ?
280328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu                EAS_12_POLICY_TYPE : EAS_2_POLICY_TYPE;
281328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu    }
282328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu}
283