1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.email.service;
18
19import android.app.Service;
20import android.app.admin.DevicePolicyManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.os.IBinder;
25import android.os.RemoteException;
26
27import com.android.email.SecurityPolicy;
28import com.android.emailcommon.provider.Policy;
29import com.android.emailcommon.service.IPolicyService;
30import com.android.mail.utils.LogTag;
31import com.android.mail.utils.LogUtils;
32
33public class PolicyService extends Service {
34    private static final String LOG_TAG = LogTag.getLogTag();
35
36    private SecurityPolicy mSecurityPolicy;
37    private Context mContext;
38
39    private final IPolicyService.Stub mBinder = new IPolicyService.Stub() {
40        @Override
41        public boolean isActive(Policy policy) {
42            try {
43                return mSecurityPolicy.isActive(policy);
44            } catch (RuntimeException e) {
45                // Catch, log and rethrow the exception, as otherwise when the exception is
46                // ultimately handled, the complete stack trace is losk
47                LogUtils.e(LOG_TAG, e, "Exception thrown during call to SecurityPolicy#isActive");
48                throw e;
49            }
50        }
51
52        @Override
53        public void setAccountHoldFlag(long accountId, boolean newState) {
54            SecurityPolicy.setAccountHoldFlag(mContext, accountId, newState);
55        }
56
57        @Override
58        public void remoteWipe() {
59            try {
60                mSecurityPolicy.remoteWipe();
61            } catch (RuntimeException e) {
62                // Catch, log and rethrow the exception, as otherwise when the exception is
63                // ultimately handled, the complete stack trace is losk
64                LogUtils.e(LOG_TAG, e, "Exception thrown during call to SecurityPolicy#remoteWipe");
65                throw e;
66            }
67        }
68
69        @Override
70        public void setAccountPolicy(long accountId, Policy policy, String securityKey) {
71            setAccountPolicy2(accountId, policy, securityKey, true /* notify */);
72        }
73
74        @Override
75        public void setAccountPolicy2(long accountId, Policy policy, String securityKey,
76                boolean notify) {
77            try {
78                mSecurityPolicy.setAccountPolicy(accountId, policy, securityKey, notify);
79            } catch (RuntimeException e) {
80                // Catch, log and rethrow the exception, as otherwise when the exception is
81                // ultimately handled, the complete stack trace is losk
82                LogUtils.e(LOG_TAG, e,
83                        "Exception thrown from call to SecurityPolicy#setAccountPolicy");
84                throw e;
85            }
86        }
87
88        public boolean canDisableCamera() {
89            // TODO: This is not a clean way to do this, but there is not currently
90            // any api that can answer the question "will disabling the camera work?"
91            // We need to answer this question here so that we can tell the server what
92            // policies we are able to support, and only apply them after it confirms that
93            // our partial support is acceptable.
94            DevicePolicyManager dpm =
95                    (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
96            final ComponentName adminName = new ComponentName(mContext, SecurityPolicy.PolicyAdmin.class);
97            final boolean cameraDisabled = dpm.getCameraDisabled(adminName);
98            if (cameraDisabled) {
99                // The camera is already disabled, by this admin.
100                // Apparently we can support disabling the camera.
101                return true;
102            } else {
103                try {
104                    dpm.setCameraDisabled(adminName, true);
105                    dpm.setCameraDisabled(adminName, false);
106                } catch (SecurityException e) {
107                    // Apparently we cannot support disabling the camera.
108                    LogUtils.w(LOG_TAG, "SecurityException checking camera disabling.");
109                    return false;
110                }
111            }
112            return true;
113        }
114
115    };
116
117    @Override
118    public IBinder onBind(Intent intent) {
119        // When we bind this service, save the context and SecurityPolicy singleton
120        mContext = this;
121        mSecurityPolicy = SecurityPolicy.getInstance(this);
122        return mBinder;
123    }
124}