com.android.strictmodetest.StrictModeActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.android.strictmodetest.StrictModeActivity.java

Source

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.strictmodetest;

import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.Config;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;

import dalvik.system.BlockGuard;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;

public class StrictModeActivity extends Activity {

    private static final String TAG = "StrictModeActivity";
    private static final Uri SYSTEM_SETTINGS_URI = Uri.parse("content://settings/system");

    private ContentResolver cr;

    private final static class SimpleConnection implements ServiceConnection {
        public IService stub = null;

        public void onServiceConnected(ComponentName name, IBinder service) {
            stub = IService.Stub.asInterface(service);
            Log.v(TAG, "Service connected: " + name);
        }

        public void onServiceDisconnected(ComponentName name) {
            stub = null;
            Log.v(TAG, "Service disconnected: " + name);
        }
    }

    private final SimpleConnection mLocalServiceConn = new SimpleConnection();
    private final SimpleConnection mRemoteServiceConn = new SimpleConnection();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        cr = getContentResolver();
        final SQLiteDatabase db = openOrCreateDatabase("foo.db", MODE_PRIVATE, null);

        final Button readButton = (Button) findViewById(R.id.read_button);
        readButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Cursor c = null;
                try {
                    c = db.rawQuery("SELECT * FROM foo", null);
                } finally {
                    if (c != null)
                        c.close();
                }
            }
        });

        final Button writeButton = (Button) findViewById(R.id.write_button);
        writeButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                db.execSQL("CREATE TABLE IF NOT EXISTS FOO (a INT)");
            }
        });

        final Button writeLoopButton = (Button) findViewById(R.id.write_loop_button);
        writeLoopButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                long startTime = SystemClock.uptimeMillis();
                int iters = 1000;
                BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
                for (int i = 0; i < iters; ++i) {
                    policy.onWriteToDisk();
                }
                long endTime = SystemClock.uptimeMillis();
                Log.d(TAG, "Time for " + iters + ": " + (endTime - startTime) + ", avg="
                        + (endTime - startTime) / (double) iters);
            }
        });

        final Button dnsButton = (Button) findViewById(R.id.dns_button);
        dnsButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "Doing DNS lookup for www.l.google.com... " + "(may be cached by InetAddress)");
                try {
                    InetAddress[] addrs = InetAddress.getAllByName("www.l.google.com");
                    for (int i = 0; i < addrs.length; ++i) {
                        Log.d(TAG, "got: " + addrs[i]);
                    }
                } catch (java.net.UnknownHostException e) {
                    Log.d(TAG, "DNS error: " + e);
                }
            }
        });

        final Button httpButton = (Button) findViewById(R.id.http_button);
        httpButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    // Note: not using AndroidHttpClient, as that comes with its
                    // own pre-StrictMode network-on-Looper thread check.  The
                    // intent of this test is that we test the network stack's
                    // instrumentation for StrictMode instead.
                    DefaultHttpClient httpClient = new DefaultHttpClient();
                    HttpResponse res = httpClient.execute(new HttpGet("http://www.android.com/favicon.ico"));
                    Log.d(TAG, "Fetched http response: " + res);
                } catch (IOException e) {
                    Log.d(TAG, "HTTP fetch error: " + e);
                }
            }
        });

        final Button http2Button = (Button) findViewById(R.id.http2_button);
        http2Button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    // Usually this ends up tripping in DNS resolution,
                    // so see http3Button below, which connects directly to an IP
                    InputStream is = new URL("http://www.android.com/").openConnection().getInputStream();
                    Log.d(TAG, "Got input stream: " + is);
                } catch (IOException e) {
                    Log.d(TAG, "HTTP fetch error: " + e);
                }
            }
        });

        final Button http3Button = (Button) findViewById(R.id.http3_button);
        http3Button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    // One of Google's web IPs, as of 2010-06-16....
                    InputStream is = new URL("http://74.125.19.14/").openConnection().getInputStream();
                    Log.d(TAG, "Got input stream: " + is);
                } catch (IOException e) {
                    Log.d(TAG, "HTTP fetch error: " + e);
                }
            }
        });

        final Button binderLocalButton = (Button) findViewById(R.id.binder_local_button);
        binderLocalButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    boolean value = mLocalServiceConn.stub.doDiskWrite(123 /* dummy */);
                    Log.d(TAG, "local writeToDisk returned: " + value);
                } catch (RemoteException e) {
                    Log.d(TAG, "local binderButton error: " + e);
                }
            }
        });

        final Button binderRemoteButton = (Button) findViewById(R.id.binder_remote_button);
        binderRemoteButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    boolean value = mRemoteServiceConn.stub.doDiskWrite(1);
                    Log.d(TAG, "remote writeToDisk #1 returned: " + value);
                    value = mRemoteServiceConn.stub.doDiskWrite(2);
                    Log.d(TAG, "remote writeToDisk #2 returned: " + value);
                } catch (RemoteException e) {
                    Log.d(TAG, "remote binderButton error: " + e);
                }
            }
        });

        final Button binderOneWayButton = (Button) findViewById(R.id.binder_oneway_button);
        binderOneWayButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    Log.d(TAG, "doing oneway disk write over Binder.");
                    mRemoteServiceConn.stub.doDiskOneWay();
                } catch (RemoteException e) {
                    Log.d(TAG, "remote binderButton error: " + e);
                }
            }
        });

        final Button binderCheckButton = (Button) findViewById(R.id.binder_check_button);
        binderCheckButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int policy;
                try {
                    policy = mLocalServiceConn.stub.getThreadPolicy();
                    Log.d(TAG, "local service policy: " + policy);
                    policy = mRemoteServiceConn.stub.getThreadPolicy();
                    Log.d(TAG, "remote service policy: " + policy);
                } catch (RemoteException e) {
                    Log.d(TAG, "binderCheckButton error: " + e);
                }
            }
        });

        final Button serviceDumpButton = (Button) findViewById(R.id.service_dump);
        serviceDumpButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.d(TAG, "About to do a service dump...");
                File file = new File("/sdcard/strictmode-service-dump.txt");
                FileOutputStream output = null;
                final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
                try {
                    StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
                    output = new FileOutputStream(file);
                    StrictMode.setThreadPolicy(oldPolicy);
                    boolean dumped = Debug.dumpService("cpuinfo", output.getFD(), new String[0]);
                    Log.d(TAG, "Dumped = " + dumped);
                } catch (IOException e) {
                    Log.e(TAG, "Can't dump service", e);
                } finally {
                    StrictMode.setThreadPolicy(oldPolicy);
                }
                Log.d(TAG, "Did service dump.");
            }
        });

        final Button lingerCloseButton = (Button) findViewById(R.id.linger_close_button);
        lingerCloseButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                closeWithLinger(true);
            }
        });

        final Button nonlingerCloseButton = (Button) findViewById(R.id.nonlinger_close_button);
        nonlingerCloseButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                closeWithLinger(false);
            }
        });

        final Button leakCursorButton = (Button) findViewById(R.id.leak_cursor_button);
        leakCursorButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                final StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
                try {
                    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects()
                            .penaltyLog().penaltyDropBox().build());
                    db.execSQL("CREATE TABLE IF NOT EXISTS FOO (a INT)");
                    Cursor c = db.rawQuery("SELECT * FROM foo", null);
                    c = null; // never close it
                    Runtime.getRuntime().gc();
                } finally {
                    StrictMode.setVmPolicy(oldPolicy);
                }

            }
        });

        final CheckBox checkNoWrite = (CheckBox) findViewById(R.id.policy_no_write);
        final CheckBox checkNoRead = (CheckBox) findViewById(R.id.policy_no_reads);
        final CheckBox checkNoNetwork = (CheckBox) findViewById(R.id.policy_no_network);
        final CheckBox checkPenaltyLog = (CheckBox) findViewById(R.id.policy_penalty_log);
        final CheckBox checkPenaltyDialog = (CheckBox) findViewById(R.id.policy_penalty_dialog);
        final CheckBox checkPenaltyDeath = (CheckBox) findViewById(R.id.policy_penalty_death);
        final CheckBox checkPenaltyDropBox = (CheckBox) findViewById(R.id.policy_penalty_dropbox);

        View.OnClickListener changePolicy = new View.OnClickListener() {
            public void onClick(View v) {
                StrictMode.ThreadPolicy.Builder newPolicy = new StrictMode.ThreadPolicy.Builder();
                if (checkNoWrite.isChecked())
                    newPolicy.detectDiskWrites();
                if (checkNoRead.isChecked())
                    newPolicy.detectDiskReads();
                if (checkNoNetwork.isChecked())
                    newPolicy.detectNetwork();
                if (checkPenaltyLog.isChecked())
                    newPolicy.penaltyLog();
                if (checkPenaltyDialog.isChecked())
                    newPolicy.penaltyDialog();
                if (checkPenaltyDeath.isChecked())
                    newPolicy.penaltyDeath();
                if (checkPenaltyDropBox.isChecked())
                    newPolicy.penaltyDropBox();
                StrictMode.ThreadPolicy policy = newPolicy.build();
                Log.v(TAG, "Changing policy to: " + policy);
                StrictMode.setThreadPolicy(policy);
            }
        };
        checkNoWrite.setOnClickListener(changePolicy);
        checkNoRead.setOnClickListener(changePolicy);
        checkNoNetwork.setOnClickListener(changePolicy);
        checkPenaltyLog.setOnClickListener(changePolicy);
        checkPenaltyDialog.setOnClickListener(changePolicy);
        checkPenaltyDeath.setOnClickListener(changePolicy);
        checkPenaltyDropBox.setOnClickListener(changePolicy);
    }

    private void closeWithLinger(boolean linger) {
        Log.d(TAG, "Socket linger test; linger=" + linger);
        try {
            Socket socket = new Socket();
            socket.setSoLinger(linger, 5);
            socket.close();
        } catch (IOException e) {
            Log.e(TAG, "Error with linger close", e);
        }
    }

    private void fileReadLoop() {
        RandomAccessFile raf = null;
        File filename = getFileStreamPath("test.dat");
        try {
            long sumNanos = 0;
            byte[] buf = new byte[512];

            //raf = new RandomAccessFile(filename, "rw");
            //raf.write(buf);
            //raf.close();
            //raf = null;

            // The data's almost certainly cached -- it's not clear what we're testing here
            raf = new RandomAccessFile(filename, "r");
            raf.seek(0);
            raf.read(buf);
        } catch (IOException e) {
            Log.e(TAG, "File read failed", e);
        } finally {
            try {
                if (raf != null)
                    raf.close();
            } catch (IOException e) {
            }
        }
    }

    // Returns milliseconds taken, or -1 on failure.
    private long settingsWrite(int mode) {
        Cursor c = null;
        long startTime = SystemClock.uptimeMillis();
        // The database will take care of replacing duplicates.
        try {
            ContentValues values = new ContentValues();
            values.put("name", "dummy_for_testing");
            values.put("value", "" + startTime);
            Uri uri = cr.insert(SYSTEM_SETTINGS_URI, values);
            Log.v(TAG, "inserted uri: " + uri);
        } catch (SQLException e) {
            Log.w(TAG, "sqliteexception during write: " + e);
            return -1;
        }
        long duration = SystemClock.uptimeMillis() - startTime;
        return duration;
    }

    @Override
    public void onResume() {
        super.onResume();
        bindService(new Intent(this, LocalService.class), mLocalServiceConn, Context.BIND_AUTO_CREATE);
        bindService(new Intent(this, RemoteService.class), mRemoteServiceConn, Context.BIND_AUTO_CREATE);
    }

    @Override
    public void onPause() {
        super.onPause();
        unbindService(mLocalServiceConn);
        unbindService(mRemoteServiceConn);
    }
}