/*
* Copyright (C) 2014-2015 asksven
*
* 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.asksven.betterbatterystats;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import com.asksven.android.common.RootShell;
import com.asksven.android.common.utils.SysUtils;
import com.asksven.android.common.utils.SystemAppInstaller;
import com.asksven.android.common.utils.SystemAppInstaller.Status;
import com.asksven.betterbatterystats.R;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class SystemAppActivity extends BaseActivity
{
final static String TAG = "BetteryInfoTest.MainActivity";
// final static String APK = "com.asksven.betterbatterystats_debug.apk";
final static String BBS_SIGNED_APK = "com.asksven.betterbatterystats_signed.apk";
final static String BBS_DEBUG_APK = "com.asksven.betterbatterystats_debug.apk";
final static String BBS_XDA_APK = "com.asksven.betterbatterystats_xdaedition.apk";
final static String RECOVERY_GPLAY = "http://better.asksven.org/bbs-systemapp/";
final static String RECOVERY_XDA = "http://forum.xda-developers.com/showpost.php?p=15869904&postcount=3";
String systemAPKName = "";
final static String PACKAGE = "com.asksven.betterbatterystats";
Object m_stats = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_systemapp);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(getString(R.string.label_system_app));
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayUseLogoEnabled(false);
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this);
if ( !RootShell.getInstance().hasRootPermissions() )
{
// show message that data is not available
// prepare the alert box
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
// set the message to display
alertbox.setMessage(getString(R.string.info_root_required));
// add a neutral button to the alert box and assign a click listener
alertbox.setNeutralButton(getString(R.string.label_button_ok), new DialogInterface.OnClickListener()
{
// click listener on the alert box
public void onClick(DialogInterface arg0, int arg1)
{
setResult(RESULT_OK);
finish();
}
});
// show it
alertbox.show();
}
// package name is either com.asksven.betterbatterystats or com.asksven.betterbatterystats_xdaedition
String packageName = getPackageName();
// now we also need to find out if this build was signed with the debug key
boolean debug = isDebuggable(this);
// determine the name of the APK to install from assets
// if package name does not contain xdaedition
// if package is signed with a debug key
// use BBS_SIGNED_APK
// else
// use BBS_DEBUG_APK
// else
// use BBS_XDA_APK
if (!packageName.contains("xdaedition"))
{
if (!debug)
{
systemAPKName = BBS_SIGNED_APK;
}
else
{
systemAPKName = BBS_DEBUG_APK;
}
}
else
{
systemAPKName = BBS_XDA_APK;
}
Log.i(TAG, "SystemAPKName = " + systemAPKName);
final TextView permBattery = (TextView) findViewById(R.id.textViewPermBATTERY_STATS);
if (hasBatteryStatsPermission(this))
{
permBattery.setText("BATTERY_STATS " + getString(R.string.label_granted));
}
else
{
permBattery.setText("BATTERY_STATS " + getString(R.string.label_not_granted));
}
final TextView permDump = (TextView) findViewById(R.id.textViewPermDUMP);
if (hasDumpPermission(this))
{
permDump.setText("DUMP " + getString(R.string.label_granted));
}
else
{
permDump.setText("DUMP " + getString(R.string.label_not_granted));
}
final TextView seLinux = (TextView) findViewById(R.id.textViewSELinux);
seLinux.setText("SELinux: " + SysUtils.getSELinuxPolicy());
final Button buttonRemount = (Button) findViewById(R.id.button2);
setButtonText(buttonRemount);
buttonRemount.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Status status;
try
{
boolean install = !SystemAppInstaller.isSystemApp(systemAPKName);
if (install)
{
status = SystemAppInstaller.install(SystemAppActivity.this, systemAPKName);
}
else
{
status = SystemAppInstaller.uninstall(PACKAGE);
}
setButtonText(buttonRemount);
if (status.getSuccess())
{
Snackbar
.make(findViewById(android.R.id.content), R.string.info_succeeded, Snackbar.LENGTH_LONG)
.show();
// Toast.makeText(SystemAppActivity.this, getString(R.string.info_succeeded), Toast.LENGTH_LONG).show();
// prepare the alert box
AlertDialog.Builder alertbox = new AlertDialog.Builder(SystemAppActivity.this);
// set the message to display
if (install)
{
alertbox.setMessage(getString(R.string.info_installed_system_app));
}
else
{
alertbox.setMessage(getString(R.string.info_uninstalled_system_app));
}
// add a neutral button to the alert box and assign a click listener
alertbox.setNeutralButton("Ok", new DialogInterface.OnClickListener()
{
// click listener on the alert box
public void onClick(DialogInterface arg0, int arg1)
{
}
});
// show it
alertbox.show();
}
else
{
Snackbar
.make(findViewById(android.R.id.content), R.string.info_failed, Snackbar.LENGTH_LONG)
.show();
// Toast.makeText(SystemAppActivity.this, getString(R.string.info_failed), Toast.LENGTH_LONG).show();
Log.e(TAG,"History: " + status.toString());
}
}
catch (Exception e)
{
Log.e(TAG, "Exception: " + Log.getStackTraceString(e));
Snackbar
.make(findViewById(android.R.id.content), R.string.info_failed, Snackbar.LENGTH_LONG)
.show();
// Toast.makeText(SystemAppActivity.this, getString(R.string.info_failed), Toast.LENGTH_LONG).show();
}
// refresh status of button
setButtonText(buttonRemount);
}
});
final Button buttonRecovery = (Button) findViewById(R.id.button3);
buttonRecovery.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String url = "";
if (isDebuggable(SystemAppActivity.this))
{
// use XDA
url = RECOVERY_XDA;
}
else
{
url = RECOVERY_GPLAY;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});
}
void setButtonText(Button button)
{
if (!RootShell.getInstance().hasRootPermissions()) return;
if (SystemAppInstaller.isSystemApp(systemAPKName))
{
button.setText(getString(R.string.uninstall_system_app));
}
else
{
button.setText(getString(R.string.install_system_app));
}
}
private boolean hasBatteryStatsPermission(Context context)
{
return wasPermissionGranted(context, android.Manifest.permission.BATTERY_STATS);
}
private boolean hasDumpPermission(Context context)
{
return wasPermissionGranted(context, android.Manifest.permission.DUMP);
}
private boolean wasPermissionGranted(Context context, String permission)
{
PackageManager pm = context.getPackageManager();
int hasPerm = pm.checkPermission(
permission,
context.getPackageName());
return (hasPerm == PackageManager.PERMISSION_GRANTED);
}
private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US");
private boolean isDebuggable(Context ctx)
{
boolean debuggable = false;
try
{
PackageInfo pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(),PackageManager.GET_SIGNATURES);
Signature signatures[] = pinfo.signatures;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
for ( int i = 0; i < signatures.length;i++)
{
ByteArrayInputStream stream = new ByteArrayInputStream(signatures[i].toByteArray());
X509Certificate cert = (X509Certificate) cf.generateCertificate(stream);
debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);
if (debuggable)
break;
}
}
catch (NameNotFoundException e)
{
//debuggable variable will remain false
}
catch (CertificateException e)
{
//debuggable variable will remain false
}
return debuggable;
}
}