19ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank/*
29ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * Copyright (C) 2011 The Android Open Source Project
39ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank *
49ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
59ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * you may not use this file except in compliance with the License.
69ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * You may obtain a copy of the License at
79ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank *
89ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
99ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank *
109ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * Unless required by applicable law or agreed to in writing, software
119ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
129ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * See the License for the specific language governing permissions and
149ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank * limitations under the License.
159ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank */
169ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
179ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankpackage com.android.email.service;
189ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
199ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankimport android.app.Service;
20ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdonimport android.app.admin.DevicePolicyManager;
21ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdonimport android.content.ComponentName;
229ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankimport android.content.Context;
239ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankimport android.content.Intent;
249ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankimport android.os.IBinder;
2534662f11b2ff38f05219415f3672a52a7af2338fTony Mantlerimport android.os.RemoteException;
269ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
27f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.email.SecurityPolicy;
28f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.emailcommon.provider.Policy;
29f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.emailcommon.service.IPolicyService;
3095bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrookimport com.android.mail.utils.LogTag;
3195bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrookimport com.android.mail.utils.LogUtils;
32f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank
339ba506c4dd498150555f6c59aa758f7467bf9236Marc Blankpublic class PolicyService extends Service {
3495bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook    private static final String LOG_TAG = LogTag.getLogTag();
359ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
369ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    private SecurityPolicy mSecurityPolicy;
379ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    private Context mContext;
389ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
399ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    private final IPolicyService.Stub mBinder = new IPolicyService.Stub() {
409e521deb6bb525b33365cc2926cb2d0faa7095e2Scott Kennedy        @Override
41aeee10e57ef4d931e7708fde218d590453a82aeaMarc Blank        public boolean isActive(Policy policy) {
4295bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            try {
4395bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                return mSecurityPolicy.isActive(policy);
4495bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            } catch (RuntimeException e) {
4595bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // Catch, log and rethrow the exception, as otherwise when the exception is
4695bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // ultimately handled, the complete stack trace is losk
4795bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                LogUtils.e(LOG_TAG, e, "Exception thrown during call to SecurityPolicy#isActive");
4895bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                throw e;
4995bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            }
509ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        }
519ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
529e521deb6bb525b33365cc2926cb2d0faa7095e2Scott Kennedy        @Override
539ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        public void setAccountHoldFlag(long accountId, boolean newState) {
549ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank            SecurityPolicy.setAccountHoldFlag(mContext, accountId, newState);
559ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        }
569ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
579e521deb6bb525b33365cc2926cb2d0faa7095e2Scott Kennedy        @Override
589ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        public void remoteWipe() {
5995bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            try {
6095bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                mSecurityPolicy.remoteWipe();
6195bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            } catch (RuntimeException e) {
6295bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // Catch, log and rethrow the exception, as otherwise when the exception is
6395bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // ultimately handled, the complete stack trace is losk
6495bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                LogUtils.e(LOG_TAG, e, "Exception thrown during call to SecurityPolicy#remoteWipe");
6595bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                throw e;
6695bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            }
679ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        }
689ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
699e521deb6bb525b33365cc2926cb2d0faa7095e2Scott Kennedy        @Override
70f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        public void setAccountPolicy(long accountId, Policy policy, String securityKey) {
7134662f11b2ff38f05219415f3672a52a7af2338fTony Mantler            setAccountPolicy2(accountId, policy, securityKey, true /* notify */);
7234662f11b2ff38f05219415f3672a52a7af2338fTony Mantler        }
7334662f11b2ff38f05219415f3672a52a7af2338fTony Mantler
7434662f11b2ff38f05219415f3672a52a7af2338fTony Mantler        @Override
7534662f11b2ff38f05219415f3672a52a7af2338fTony Mantler        public void setAccountPolicy2(long accountId, Policy policy, String securityKey,
7634662f11b2ff38f05219415f3672a52a7af2338fTony Mantler                boolean notify) {
7795bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            try {
7834662f11b2ff38f05219415f3672a52a7af2338fTony Mantler                mSecurityPolicy.setAccountPolicy(accountId, policy, securityKey, notify);
7995bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            } catch (RuntimeException e) {
8095bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // Catch, log and rethrow the exception, as otherwise when the exception is
8195bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                // ultimately handled, the complete stack trace is losk
8295bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                LogUtils.e(LOG_TAG, e,
8395bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                        "Exception thrown from call to SecurityPolicy#setAccountPolicy");
8495bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook                throw e;
8595bb350f38d08beeabee68323b8514f3cbfd5db5Paul Westbrook            }
869ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        }
87ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon
88ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon        public boolean canDisableCamera() {
89ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            // TODO: This is not a clean way to do this, but there is not currently
90ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            // any api that can answer the question "will disabling the camera work?"
91ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            // We need to answer this question here so that we can tell the server what
92ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            // policies we are able to support, and only apply them after it confirms that
93ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            // our partial support is acceptable.
94ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            DevicePolicyManager dpm =
95ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
96ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            final ComponentName adminName = new ComponentName(mContext, SecurityPolicy.PolicyAdmin.class);
97ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            final boolean cameraDisabled = dpm.getCameraDisabled(adminName);
98ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            if (cameraDisabled) {
99ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                // The camera is already disabled, by this admin.
100ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                // Apparently we can support disabling the camera.
101ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                return true;
102ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            } else {
103ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                try {
104ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    dpm.setCameraDisabled(adminName, true);
105ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    dpm.setCameraDisabled(adminName, false);
106ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                } catch (SecurityException e) {
107ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    // Apparently we cannot support disabling the camera.
108ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    LogUtils.w(LOG_TAG, "SecurityException checking camera disabling.");
109ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                    return false;
110ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon                }
111ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            }
112ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon            return true;
113ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon        }
114ce6916b32a98a568ceafb734d050801f4459a532Martin Hibdon
1159ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    };
1169ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank
1179ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    @Override
1189ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    public IBinder onBind(Intent intent) {
1199ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        // When we bind this service, save the context and SecurityPolicy singleton
1209ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        mContext = this;
1219ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        mSecurityPolicy = SecurityPolicy.getInstance(this);
1229ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank        return mBinder;
1239ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank    }
1249ba506c4dd498150555f6c59aa758f7467bf9236Marc Blank}