1 package com.koushikdutta.superuser;
3 import java.io.DataInputStream;
4 import java.io.IOException;
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;
25 public class MainActivity extends Activity {
26 private static final String LOGTAG = "Superuser";
31 ArrayAdapter<PackageInfo> mAdapter;
33 Handler mHandler = new Handler();
43 mSocket.getOutputStream().write((mAction ? "socket:ALLOW" : "socket:DENY").getBytes());
45 catch (Exception ex) {
51 protected void onDestroy() {
57 catch (Exception ex) {
62 findViewById(R.id.incoming).setVisibility(View.GONE);
63 findViewById(R.id.ready).setVisibility(View.VISIBLE);
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));
73 ((TextView)findViewById(R.id.uid_header)).setText(Integer.toString(mDesiredUid));
74 ((TextView)findViewById(R.id.command_header)).setText(mDesiredCmd);
76 mAdapter = new ArrayAdapter<PackageInfo>(this, R.layout.packageinfo, R.id.title) {
78 public View getView(int position, View convertView, ViewGroup parent) {
79 convertView = super.getView(position, convertView, parent);
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));
90 list.setAdapter(mAdapter);
91 for (String pkg: pkgs) {
93 PackageInfo pi = pm.getPackageInfo(pkg, 0);
94 ((TextView)findViewById(R.id.request)).setText(getString(R.string.application_request, pi.applicationInfo.loadLabel(pm)));
96 ((TextView)findViewById(R.id.app_header)).setText(pi.applicationInfo.loadLabel(pm));
97 ((TextView)findViewById(R.id.package_header)).setText(pi.packageName);
99 catch (Exception ex) {
105 mAllow.setText(getString(R.string.allow) + " (" + mTimeLeft + ")");
106 if (mTimeLeft-- <= 0) {
107 mAllow.setText(getString(R.string.allow));
109 mAllow.setEnabled(true);
112 mHandler.postDelayed(this, 1000);
117 void manageSocket(final String socket) {
122 mSocket = new LocalSocket();
123 mSocket.connect(new LocalSocketAddress(socket, Namespace.FILESYSTEM));
125 DataInputStream is = new DataInputStream(mSocket.getInputStream());
127 int protocolVersion = is.readInt();
128 Log.d(LOGTAG, "INT32:PROTO VERSION = " + protocolVersion);
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);
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");
144 byte[] buf = new byte[exeSize];
146 String callerBin = new String(buf, 0, exeSize - 1);
147 Log.d(LOGTAG, "STRING:EXE = " + callerBin);
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");
154 buf = new byte[cmdSize];
156 mDesiredCmd = new String(buf, 0, cmdSize - 1);
157 Log.d(LOGTAG, "STRING:CMD = " + mDesiredCmd);
158 runOnUiThread(new Runnable() {
165 catch (Exception ex) {
166 Log.i(LOGTAG, ex.getMessage(), ex);
170 catch (Exception e) {
172 runOnUiThread(new Runnable() {
185 protected void onCreate(Bundle savedInstanceState) {
186 super.onCreate(savedInstanceState);
187 setContentView(R.layout.activity_main);
189 Intent intent = getIntent();
190 if (intent == null) {
195 String socket = intent.getStringExtra("socket");
196 if (socket == null) {
201 if (getClass() == MainActivity.class) {
202 // if another su request comes in, let's start a new task for this thing.
203 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
204 intent.setClass(this, MultitaskSuRequestActivity.class);
205 startActivity(intent);
210 mAllow = (Button)findViewById(R.id.allow);
211 mDeny = (Button)findViewById(R.id.deny);
213 mAllow.setOnClickListener(new OnClickListener() {
215 public void onClick(View v) {
217 mAllow.setEnabled(false);
218 mDeny.setEnabled(false);
222 mDeny.setOnClickListener(new OnClickListener() {
224 public void onClick(View v) {
226 mAllow.setEnabled(false);
227 mDeny.setEnabled(false);
231 manageSocket(socket);