1/*
2 * Copyright (C) 2012 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.fakeoemfeatures;
18
19import android.app.ActivityManager;
20import android.app.ActivityThread;
21import android.app.AlertDialog;
22import android.app.Application;
23import android.app.Dialog;
24import android.content.ComponentName;
25import android.content.Context;
26import android.content.Intent;
27import android.content.ServiceConnection;
28import android.os.Handler;
29import android.os.IBinder;
30import android.os.Message;
31import android.util.Slog;
32import android.view.Display;
33import android.view.ViewGroup;
34import android.view.WindowManager;
35
36public class FakeApp extends Application {
37    // Stuffing of 20MB
38    static final int STUFFING_SIZE_BYTES = 20*1024*1024;
39    static final int STUFFING_SIZE_INTS = STUFFING_SIZE_BYTES/4;
40    int[] mStuffing;
41
42    // Assume 4k pages.
43    static final int PAGE_SIZE = 4*1024;
44
45    static final long TICK_DELAY = 4*60*60*1000; // One hour
46    static final int MSG_TICK = 1;
47    final Handler mHandler = new Handler() {
48        @Override public void handleMessage(Message msg) {
49            switch (msg.what) {
50                case MSG_TICK:
51                    // Our service is IMPORTANT.  We know, we wrote it.
52                    // We need to keep that thing running.  Because WE KNOW.
53                    // Damn you users, STOP MESSING WITH US.
54                    startService(new Intent(FakeApp.this, FakeBackgroundService.class));
55                    sendEmptyMessageDelayed(MSG_TICK, TICK_DELAY);
56                    break;
57                default:
58                    super.handleMessage(msg);
59                    break;
60            }
61        }
62    };
63
64    // Always run another process for more per-process overhead.
65    ServiceConnection mServiceConnection = new ServiceConnection() {
66        @Override public void onServiceConnected(ComponentName name, IBinder service) {
67        }
68
69        @Override public void onServiceDisconnected(ComponentName name) {
70        }
71    };
72    ServiceConnection mServiceConnection2 = new ServiceConnection() {
73        @Override public void onServiceConnected(ComponentName name, IBinder service) {
74        }
75
76        @Override public void onServiceDisconnected(ComponentName name) {
77        }
78    };
79    ServiceConnection mServiceConnection3 = new ServiceConnection() {
80        @Override public void onServiceConnected(ComponentName name, IBinder service) {
81        }
82
83        @Override public void onServiceDisconnected(ComponentName name) {
84        }
85    };
86
87    @Override
88    public void onCreate() {
89        String processName = ActivityThread.currentPackageName();
90        Slog.i("FakeOEMFeatures", "Creating app in process: " + processName);
91        if (!getApplicationInfo().packageName.equals(processName)) {
92            // If we are not in the main process of the app, then don't do
93            // our extra overhead stuff.
94            return;
95        }
96
97        final WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
98        final Display display = wm.getDefaultDisplay();
99
100        // Check to make sure we are not running on a user build.  If this
101        // is a user build, WARN!  Do not want!
102        if ("user".equals(android.os.Build.TYPE)) {
103            AlertDialog.Builder builder = new AlertDialog.Builder(this);
104            builder.setTitle("Should not be on user build");
105            builder.setMessage("The app Fake OEM Features should not be installed on a "
106                    + "user build.  Please remove this .apk before shipping this build to "
107                    + " your customers!");
108            builder.setCancelable(false);
109            builder.setPositiveButton("I understand", null);
110            Dialog dialog = builder.create();
111            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
112            dialog.show();
113        }
114
115        // Make a fake window that is always around eating graphics resources.
116        FakeView view = new FakeView(this);
117        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
118                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
119                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
120                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
121                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
122        if (ActivityManager.isHighEndGfx()) {
123            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
124        }
125        lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
126        lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
127        int maxSize = display.getMaximumSizeDimension();
128        maxSize *= 2;
129        lp.x = maxSize;
130        lp.y = maxSize;
131        lp.setTitle(getPackageName());
132        wm.addView(view, lp);
133
134        // Bind to a fake service we want to keep running in another process.
135        bindService(new Intent(this, FakeCoreService.class), mServiceConnection,
136                Context.BIND_AUTO_CREATE);
137        bindService(new Intent(this, FakeCoreService2.class), mServiceConnection2,
138                Context.BIND_AUTO_CREATE);
139        bindService(new Intent(this, FakeCoreService3.class), mServiceConnection3,
140                Context.BIND_AUTO_CREATE);
141
142        // Start to a fake service that should run in the background of
143        // another process.
144        mHandler.sendEmptyMessage(MSG_TICK);
145
146        // Make a fake allocation to consume some RAM.
147        mStuffing = new int[STUFFING_SIZE_INTS];
148        for (int i=0; i<STUFFING_SIZE_BYTES/PAGE_SIZE; i++) {
149            // Fill each page with a unique value.
150            final int VAL = i*2 + 100;
151            final int OFF = (i*PAGE_SIZE)/4;
152            for (int j=0; j<(PAGE_SIZE/4); j++) {
153                mStuffing[OFF+j] = VAL;
154            }
155        }
156    }
157}
158