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