• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 
17 package com.android.cts.verifier.security;
18 
19 import android.app.Service;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.ActivityNotFoundException;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.os.IBinder;
25 import android.util.Log;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.View.OnClickListener;
29 import android.view.ViewGroup;
30 import android.widget.Button;
31 import android.widget.ImageView;
32 import android.widget.TextView;
33 
34 import com.android.cts.verifier.PassFailButtons;
35 import com.android.cts.verifier.R;
36 
37 import java.io.File;
38 import java.io.FileOutputStream;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.concurrent.LinkedBlockingQueue;
42 
43 public class CAInstallNotificationVerifierActivity extends PassFailButtons.Activity
44 implements Runnable {
45     static final String TAG = CAInstallNotificationVerifierActivity.class.getSimpleName();
46     private static final String STATE = "state";
47     private static final int PASS = 1;
48     private static final int FAIL = 2;
49     private static final int WAIT_FOR_USER = 3;
50     private static LinkedBlockingQueue<String> sDeletedQueue = new LinkedBlockingQueue<String>();
51 
52     private int mState;
53     private int[] mStatus;
54     private LayoutInflater mInflater;
55     private ViewGroup mItemList;
56     private Runnable mRunner;
57     private View mHandler;
58 
59     private static final String CERT_ASSET_NAME = "myCA.cer";
60     private File certStagingFile = new File("/sdcard/", CERT_ASSET_NAME);
61 
62     protected boolean doneInstallingCert = false;
63     protected boolean doneCheckingInSettings = false;
64     protected boolean doneRemovingScreenLock = false;
65     protected boolean doneCheckingNotification = false;
66     protected boolean doneDismissingNotification = false;
67 
68 
69     public static class DismissService extends Service {
70         @Override
onBind(Intent intent)71         public IBinder onBind(Intent intent) {
72             return null;
73         }
74 
75         @Override
onStart(Intent intent, int startId)76         public void onStart(Intent intent, int startId) {
77             sDeletedQueue.offer(intent.getAction());
78         }
79     }
80 
81     @Override
onCreate(Bundle savedInstanceState)82     protected void onCreate(Bundle savedInstanceState) {
83         super.onCreate(savedInstanceState);
84 
85         if (savedInstanceState != null) {
86             mState = savedInstanceState.getInt(STATE, 0);
87         }
88         mRunner = this;
89         mInflater = getLayoutInflater();
90         View view = mInflater.inflate(R.layout.cainstallnotify_main, null);
91         mItemList = (ViewGroup) view.findViewById(R.id.ca_notify_test_items);
92         mHandler = mItemList;
93         createTestItems();
94         mStatus = new int[mItemList.getChildCount()];
95         setContentView(view);
96 
97         setPassFailButtonClickListeners();
98         setInfoResources(R.string.cacert_test, R.string.cacert_info, -1);
99     }
100 
101     @Override
onSaveInstanceState(Bundle outState)102     protected void onSaveInstanceState (Bundle outState) {
103         outState.putInt(STATE, mState);
104     }
105 
106     @Override
onResume()107     protected void onResume() {
108         super.onResume();
109         next();
110     }
111 
112     // Interface Utilities
113 
createTestItems()114     private void createTestItems() {
115         createUserItem(R.string.cacert_install_cert, new InstallCert());
116         createUserItem(R.string.cacert_check_cert_in_settings, new OpenTrustedCredentials());
117         createUserItem(R.string.cacert_remove_screen_lock, new RemoveScreenLock());
118         createUserItem(R.string.cacert_check_notification,
119                 new DoneCheckingNotification(), R.string.cacert_done);
120         createUserItem(R.string.cacert_dismiss_notification,
121                 new DoneCheckingDismissed(), R.string.cacert_done);
122     }
123 
setItemState(int index, boolean passed)124     private void setItemState(int index, boolean passed) {
125         ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
126         ImageView status = (ImageView) item.findViewById(R.id.ca_notify_status);
127         status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
128         View button = item.findViewById(R.id.ca_notify_do_something);
129         button.setClickable(false);
130         button.setEnabled(false);
131         status.invalidate();
132     }
133 
markItemWaiting(int index)134     private void markItemWaiting(int index) {
135         ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
136         ImageView status = (ImageView) item.findViewById(R.id.ca_notify_status);
137         status.setImageResource(R.drawable.fs_warning);
138         status.invalidate();
139     }
140 
createUserItem(int stringId, OnClickListener listener)141     private View createUserItem(int stringId, OnClickListener listener) {
142         return createUserItem(stringId, listener, 0);
143     }
144 
createUserItem(int stringId, OnClickListener listener, int buttonLabel)145     private View createUserItem(int stringId, OnClickListener listener, int buttonLabel) {
146         View item = mInflater.inflate(R.layout.cainstallnotify_item, mItemList, false);
147         TextView instructions = (TextView) item.findViewById(R.id.ca_notify_instructions);
148         instructions.setText(stringId);
149         Button button = (Button) item.findViewById(R.id.ca_notify_do_something);
150         if (buttonLabel != 0) {
151             button.setText(buttonLabel);
152         }
153         button.setOnClickListener(listener);
154         mItemList.addView(item);
155         return item;
156     }
157 
158     // Test management
159 
run()160     public void run() {
161         while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
162             if (mStatus[mState] == PASS) {
163                 setItemState(mState, true);
164                 mState++;
165             } else if (mStatus[mState] == FAIL) {
166                 setItemState(mState, false);
167                 return;
168             } else {
169                 break;
170             }
171         }
172 
173         if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
174             markItemWaiting(mState);
175         }
176 
177         switch (mState) {
178             case 0:
179                 testInstalledCert(0);
180                 break;
181             case 1:
182                 testCheckedSettings(1);
183                 break;
184             case 2:
185                 testRemovedScreenLock(2);
186                 break;
187             case 3:
188                 testCheckedNotification(3);
189                 break;
190             case 4:
191                 testNotificationDismissed(4);
192                 break;
193         }
194     }
195 
196     /**
197      * Return to the state machine to progress through the tests.
198      */
next()199     private void next() {
200         mHandler.post(mRunner);
201     }
202 
203     /**
204      * Wait for things to settle before returning to the state machine.
205      */
delay()206     private void delay() {
207         mHandler.postDelayed(mRunner, 2000);
208     }
209 
210     // Listeners
211 
212     class InstallCert implements OnClickListener {
213         @Override
onClick(View v)214         public void onClick(View v) {
215             InputStream is = null;
216             FileOutputStream os = null;
217             try {
218                 try {
219                     is = getAssets().open(CERT_ASSET_NAME);
220                     os = new FileOutputStream(certStagingFile);
221                     byte[] buffer = new byte[1024];
222                     int length;
223                     while ((length = is.read(buffer)) > 0) {
224                         os.write(buffer, 0, length);
225                     }
226                 } finally {
227                     if (is != null) is.close();
228                     if (os != null) os.close();
229                     certStagingFile.setReadable(true, false);
230                 }
231             } catch (IOException ioe) {
232                 Log.w(TAG, "Problem moving cert file to /sdcard/", ioe);
233                 return;
234             }
235             try {
236                 startActivity(new Intent("android.credentials.INSTALL"));
237             } catch (ActivityNotFoundException e) {
238                 // do nothing
239             }
240             doneInstallingCert = true;
241         }
242     }
243 
244     class OpenTrustedCredentials implements OnClickListener {
245         @Override
onClick(View v)246         public void onClick(View v) {
247             try {
248                 startActivity(new Intent("com.android.settings.TRUSTED_CREDENTIALS_USER"));
249             } catch (ActivityNotFoundException e) {
250                 // do nothing
251             }
252             doneCheckingInSettings = true;
253         }
254     }
255 
256     class RemoveScreenLock implements OnClickListener {
257         @Override
onClick(View v)258         public void onClick(View v) {
259             try {
260                 startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
261             } catch (ActivityNotFoundException e) {
262                 Log.w(TAG, "Activity not found for ACTION_SET_NEW_PASSWORD");
263             }
264             doneRemovingScreenLock = true;
265         }
266     }
267 
268     class DoneCheckingNotification implements OnClickListener {
269         @Override
onClick(View v)270         public void onClick(View v) {
271             doneCheckingNotification = true;
272         }
273     }
274 
275     class DoneCheckingDismissed implements OnClickListener {
276         @Override
onClick(View v)277         public void onClick(View v) {
278             doneDismissingNotification = true;
279         }
280     }
281 
282     // Tests
283 
testInstalledCert(final int i)284     private void testInstalledCert(final int i) {
285         if (doneInstallingCert) {
286             mStatus[i] = PASS;
287             next();
288         } else {
289             delay();
290         }
291     }
292 
testCheckedSettings(final int i)293     private void testCheckedSettings(final int i) {
294         if (doneCheckingInSettings) {
295             mStatus[i] = PASS;
296             next();
297         } else {
298             delay();
299         }
300     }
301 
testRemovedScreenLock(final int i)302     private void testRemovedScreenLock(final int i) {
303         if (doneRemovingScreenLock) {
304             mStatus[i] = PASS;
305             next();
306         } else {
307             delay();
308         }
309     }
310 
testCheckedNotification(final int i)311     private void testCheckedNotification(final int i) {
312         if (doneCheckingNotification) {
313             mStatus[i] = PASS;
314             next();
315         } else {
316             delay();
317         }
318     }
319 
testNotificationDismissed(final int i)320     private void testNotificationDismissed(final int i) {
321         if (doneDismissingNotification) {
322             mStatus[i] = PASS;
323             next();
324         } else {
325             delay();
326         }
327     }
328 }
329