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.settings;
18
19import android.app.Activity;
20import android.app.StatusBarManager;
21import android.content.Context;
22import android.content.Intent;
23import android.os.Bundle;
24import android.os.Handler;
25import android.os.IBinder;
26import android.os.ServiceManager;
27import android.os.UserHandle;
28import android.os.storage.IStorageManager;
29import android.provider.Settings;
30import android.util.Log;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34import android.widget.Button;
35
36import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
37import com.android.internal.widget.LockPatternUtils;
38import com.android.settings.core.InstrumentedPreferenceFragment;
39
40import java.util.Locale;
41
42public class CryptKeeperConfirm extends InstrumentedPreferenceFragment {
43
44    private static final String TAG = "CryptKeeperConfirm";
45
46    @Override
47    public int getMetricsCategory() {
48        return MetricsEvent.CRYPT_KEEPER_CONFIRM;
49    }
50
51    public static class Blank extends Activity {
52        private Handler mHandler = new Handler();
53
54        @Override
55        public void onCreate(Bundle savedInstanceState) {
56            super.onCreate(savedInstanceState);
57
58            setContentView(R.layout.crypt_keeper_blank);
59
60            if (Utils.isMonkeyRunning()) {
61                finish();
62            }
63
64            StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
65            sbm.disable(StatusBarManager.DISABLE_EXPAND
66                    | StatusBarManager.DISABLE_NOTIFICATION_ICONS
67                    | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
68                    | StatusBarManager.DISABLE_SYSTEM_INFO
69                    | StatusBarManager.DISABLE_HOME
70                    | StatusBarManager.DISABLE_SEARCH
71                    | StatusBarManager.DISABLE_RECENT
72                    | StatusBarManager.DISABLE_BACK);
73
74            // Post a delayed message in 700 milliseconds to enable encryption.
75            // NOTE: The animation on this activity is set for 500 milliseconds
76            // I am giving it a little extra time to complete.
77            mHandler.postDelayed(new Runnable() {
78                public void run() {
79                    IBinder service = ServiceManager.getService("mount");
80                    if (service == null) {
81                        Log.e("CryptKeeper", "Failed to find the mount service");
82                        finish();
83                        return;
84                    }
85
86                    IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
87                    try {
88                        Bundle args = getIntent().getExtras();
89                        storageManager.encryptStorage(args.getInt("type", -1), args.getString("password"));
90                    } catch (Exception e) {
91                        Log.e("CryptKeeper", "Error while encrypting...", e);
92                    }
93                }
94            }, 700);
95        }
96    }
97
98    private View mContentView;
99    private Button mFinalButton;
100    private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
101
102        public void onClick(View v) {
103            if (Utils.isMonkeyRunning()) {
104                return;
105            }
106
107            /* WARNING - nasty hack!
108               Settings for the lock screen are not available to the crypto
109               screen (CryptKeeper) at boot. We duplicate the ones that
110               CryptKeeper needs to the crypto key/value store when they are
111               modified (see LockPatternUtils).
112               However, prior to encryption, the crypto key/value store is not
113               persisted across reboots, thus modified settings are lost to
114               CryptKeeper.
115               In order to make sure CryptKeeper had the correct settings after
116               first encrypting, we thus need to rewrite them, which ensures the
117               crypto key/value store is up to date. On encryption, this store
118               is then persisted, and the settings will be there on future
119               reboots.
120             */
121
122            // 1. The owner info.
123            LockPatternUtils utils = new LockPatternUtils(getActivity());
124            utils.setVisiblePatternEnabled(
125                    utils.isVisiblePatternEnabled(UserHandle.USER_SYSTEM),
126                    UserHandle.USER_SYSTEM);
127            if (utils.isOwnerInfoEnabled(UserHandle.USER_SYSTEM)) {
128                utils.setOwnerInfo(utils.getOwnerInfo(UserHandle.USER_SYSTEM),
129                                   UserHandle.USER_SYSTEM);
130            }
131            int value = Settings.System.getInt(getContext().getContentResolver(),
132                                               Settings.System.TEXT_SHOW_PASSWORD,
133                                               1);
134            utils.setVisiblePasswordEnabled(value != 0, UserHandle.USER_SYSTEM);
135
136            Intent intent = new Intent(getActivity(), Blank.class);
137            intent.putExtras(getArguments());
138            startActivity(intent);
139
140            // 2. The system locale.
141            try {
142                IBinder service = ServiceManager.getService("mount");
143                IStorageManager storageManager = IStorageManager.Stub.asInterface(service);
144                storageManager.setField("SystemLocale", Locale.getDefault().toLanguageTag());
145            } catch (Exception e) {
146                Log.e(TAG, "Error storing locale for decryption UI", e);
147            }
148        }
149    };
150
151    private void establishFinalConfirmationState() {
152        mFinalButton = (Button) mContentView.findViewById(R.id.execute_encrypt);
153        mFinalButton.setOnClickListener(mFinalClickListener);
154    }
155
156    @Override
157    public View onCreateView(LayoutInflater inflater, ViewGroup container,
158            Bundle savedInstanceState) {
159        mContentView = inflater.inflate(R.layout.crypt_keeper_confirm, null);
160        establishFinalConfirmationState();
161        return mContentView;
162    }
163}
164