OSDN Git Service

i gud at english
[android-x86/external-koush-Superuser.git] / Superuser / src / com / koushikdutta / superuser / MainActivity.java
1 package com.koushikdutta.superuser;
2
3 import java.io.DataInputStream;
4 import java.io.IOException;
5
6 import android.app.Activity;
7 import android.content.Intent;
8 import android.content.pm.PackageInfo;
9 import android.content.pm.PackageManager;
10 import android.net.LocalSocket;
11 import android.net.LocalSocketAddress;
12 import android.net.LocalSocketAddress.Namespace;
13 import android.os.Bundle;
14 import android.os.Handler;
15 import android.util.Log;
16 import android.view.View;
17 import android.view.View.OnClickListener;
18 import android.view.ViewGroup;
19 import android.widget.ArrayAdapter;
20 import android.widget.Button;
21 import android.widget.ImageView;
22 import android.widget.ListView;
23 import android.widget.TextView;
24
25 public class MainActivity extends Activity {
26     private static final String LOGTAG = "Superuser";
27     int mCallerUid;
28     int mDesiredUid;
29     String mDesiredCmd;
30     
31     ArrayAdapter<PackageInfo> mAdapter;
32     
33     Handler mHandler = new Handler();
34     
35     int mTimeLeft = 3;
36     
37     Boolean mAction;
38     Button mAllow;
39     Button mDeny;
40
41     void handleAction() {
42         try {
43             mSocket.getOutputStream().write((mAction ? "socket:ALLOW" : "socket:DENY").getBytes());
44         }
45         catch (Exception ex) {
46         }
47         finish();
48     }
49     
50     @Override
51     protected void onDestroy() {
52         super.onDestroy();
53         try {
54             if (mSocket != null)
55                 mSocket.close();
56         }
57         catch (Exception ex) {
58         }
59     }
60     
61     void requestReady() {
62         findViewById(R.id.incoming).setVisibility(View.GONE);
63         findViewById(R.id.ready).setVisibility(View.VISIBLE);
64         
65         ListView list = (ListView)findViewById(R.id.list);
66         list.setEnabled(false);
67         list.setEmptyView(findViewById(R.id.unknown));
68         final PackageManager pm = getPackageManager();
69         String[] pkgs = pm.getPackagesForUid(mCallerUid);
70         TextView unknown = (TextView)findViewById(R.id.unknown);
71         unknown.setText(getString(R.string.unknown_uid, mCallerUid));
72         
73         ((TextView)findViewById(R.id.uid_header)).setText(Integer.toString(mDesiredUid));
74         ((TextView)findViewById(R.id.command_header)).setText(mDesiredCmd);
75
76         mAdapter = new ArrayAdapter<PackageInfo>(this, R.layout.packageinfo, R.id.title) {
77             @Override
78             public View getView(int position, View convertView, ViewGroup parent) {
79                 convertView = super.getView(position, convertView, parent);
80                 
81                 PackageInfo pi = getItem(position);
82                 ImageView icon = (ImageView)convertView.findViewById(R.id.image);
83                 icon.setImageDrawable(pi.applicationInfo.loadIcon(pm));
84                 ((TextView)convertView.findViewById(R.id.title)).setText(pi.applicationInfo.loadLabel(pm));
85                 
86                 return convertView;
87             }
88         };
89         
90         list.setAdapter(mAdapter);
91         for (String pkg: pkgs) {
92             try {
93                 PackageInfo pi = pm.getPackageInfo(pkg, 0);
94                 ((TextView)findViewById(R.id.request)).setText(getString(R.string.application_request, pi.applicationInfo.loadLabel(pm)));
95                 mAdapter.add(pi);
96                 ((TextView)findViewById(R.id.app_header)).setText(pi.applicationInfo.loadLabel(pm));
97                 ((TextView)findViewById(R.id.package_header)).setText(pi.packageName);
98             }
99             catch (Exception ex) {
100             }
101         }
102         
103         new Runnable() {
104             public void run() {
105                 mAllow.setText(getString(R.string.allow) + " (" + mTimeLeft + ")");
106                 if (mTimeLeft-- <= 0) {
107                     mAllow.setText(getString(R.string.allow));
108                     if (mAction == null)
109                         mAllow.setEnabled(true);
110                     return;
111                 }
112                 mHandler.postDelayed(this, 1000);
113             };
114         }.run();
115     }
116
117     void manageSocket(final String socket) {
118         new Thread() {
119             @Override
120             public void run() {
121                 try {
122                     mSocket = new LocalSocket();
123                     mSocket.connect(new LocalSocketAddress(socket, Namespace.FILESYSTEM));
124
125                     DataInputStream is = new DataInputStream(mSocket.getInputStream());
126
127                     int protocolVersion = is.readInt();
128                     Log.d(LOGTAG, "INT32:PROTO VERSION = " + protocolVersion);
129
130                     int exeSizeMax = is.readInt();
131                     Log.d(LOGTAG, "UINT32:FIELD7MAX = " + exeSizeMax);
132                     int cmdSizeMax = is.readInt();
133                     Log.d(LOGTAG, "UINT32:FIELD9MAX = " + cmdSizeMax);
134                     mCallerUid = is.readInt();
135                     Log.d(LOGTAG, "UINT32:CALLER = " + mCallerUid);
136                     mDesiredUid = is.readInt();
137                     Log.d(LOGTAG, "UINT32:TO = " + mDesiredUid);
138
139                     int exeSize = is.readInt();
140                     Log.d(LOGTAG, "UINT32:EXESIZE = " + exeSize);
141                     if (exeSize > exeSizeMax) {
142                         throw new IOException("Incomming string bigger than allowed");
143                     }
144                     byte[] buf = new byte[exeSize];
145                     is.read(buf);
146                     String callerBin = new String(buf, 0, exeSize - 1);
147                     Log.d(LOGTAG, "STRING:EXE = " + callerBin);
148
149                     int cmdSize = is.readInt();
150                     Log.d(LOGTAG, "UINT32:CMDSIZE = " + cmdSize);
151                     if (cmdSize > cmdSizeMax) {
152                         throw new IOException("Incomming string bigger than allowed");
153                     }
154                     buf = new byte[cmdSize];
155                     is.read(buf);
156                     mDesiredCmd = new String(buf, 0, cmdSize - 1);
157                     Log.d(LOGTAG, "STRING:CMD = " + mDesiredCmd);
158                     runOnUiThread(new Runnable() {
159                         @Override
160                         public void run() {
161                             requestReady();
162                         }
163                     });
164                 }
165                 catch (Exception ex) {
166                     Log.i(LOGTAG, ex.getMessage(), ex);
167                     try {
168                         mSocket.close();
169                     }
170                     catch (Exception e) {
171                     }
172                     runOnUiThread(new Runnable() {
173                         @Override
174                         public void run() {
175                             finish();
176                         }
177                     });
178                 }
179             }
180         }.start();
181     }
182     
183     LocalSocket mSocket;
184     @Override
185     protected void onCreate(Bundle savedInstanceState) {
186         super.onCreate(savedInstanceState);
187         setContentView(R.layout.activity_main);
188         
189         Intent intent = getIntent();
190         if (intent == null) {
191             finish();
192             return;
193         }
194
195         String socket = intent.getStringExtra("socket");
196         if (socket == null) {
197             finish();
198             return;
199         }
200      
201         if (getClass() == MainActivity.class) {
202             // MainActivity is actually just a passthrough to a new task
203             // stack.
204             // Pretty much every superuser implementation i've seen craps out if there
205             // is more than 1 su request at a time. Each subsequent su request
206             // will get "lost" because there can only be one instance of the activity
207             // at a time. Really annoying. This fixes that.
208             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
209             intent.setClass(this, MultitaskSuRequestActivity.class);
210             startActivity(intent);
211             finish();
212             return;
213         }
214
215         mAllow = (Button)findViewById(R.id.allow);
216         mDeny = (Button)findViewById(R.id.deny);
217         
218         mAllow.setOnClickListener(new OnClickListener() {
219             @Override
220             public void onClick(View v) {
221                 mAction = true;
222                 mAllow.setEnabled(false);
223                 mDeny.setEnabled(false);
224                 handleAction();
225             }
226         });
227         mDeny.setOnClickListener(new OnClickListener() {
228             @Override
229             public void onClick(View v) {
230                 mAction = false;
231                 mAllow.setEnabled(false);
232                 mDeny.setEnabled(false);
233                 handleAction();
234             }
235         });
236         manageSocket(socket);
237     }
238 }