| // Copyright (C) 2015 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 gapii |
| |
| import ( |
| "fmt" |
| "os" |
| "path/filepath" |
| |
| "android.googlesource.com/platform/tools/gpu/adb" |
| "android.googlesource.com/platform/tools/gpu/log" |
| ) |
| |
| const preloadPath = "/data/gapii.so" |
| |
| var abiToSo = map[string]string{ |
| "armeabi-v7a": "android-arm", |
| "arm64-v8a": "android-arm64", |
| } |
| |
| func getSoName(a *adb.Action) (string, error) { |
| abi := a.Package.ABI |
| if abi == "" { |
| abi = a.Package.Device.Abi() |
| } |
| so, ok := abiToSo[abi] |
| if !ok { |
| return "", fmt.Errorf("Unknown device abi: %s", abi) |
| } |
| return so, nil |
| } |
| |
| func getSoPath(a *adb.Action, debug bool) (string, error) { |
| // TODO: decide how we are going to find the so's |
| gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] |
| soName, err := getSoName(a) |
| if err != nil { |
| return "", err |
| } |
| flavor := "release" |
| if debug { |
| flavor = "debug" |
| } |
| return filepath.Join(gopath, "bin", soName, flavor, "spy.so"), nil |
| } |
| |
| // AdbStart launches an activity on an android device with the gapii tracer |
| // enabled. Gapii will attempt to connect back on the specified host port to |
| // write the trace. |
| func AdbStart(l log.Logger, a *adb.Action, spyport adb.Port, debug bool) error { |
| p := a.Package |
| d := p.Device |
| enforced, err := d.SELinuxEnforcing() |
| if err != nil { |
| log.Errorf(l, "Failed detecting se linux enforcing state: %s", err) |
| return err |
| } |
| if enforced { |
| log.Infof(l, "Disabling SELinux enforcing") |
| err := d.SetSELinuxEnforcing(false) |
| if err != nil { |
| log.Errorf(l, "Failed disabling se linux enforcing: %s", err) |
| return err |
| } |
| defer func() { |
| log.Infof(l, "Re-enabling SELinux enforcing") |
| err := d.SetSELinuxEnforcing(false) |
| if err != nil { |
| log.Errorf(l, "Failed re-enabling se linux enforcing: %s", err) |
| } |
| }() |
| } |
| |
| gapiiPath, err := getSoPath(a, debug) |
| if err != nil { |
| log.Errorf(l, "Failed finding gapii: %s", err) |
| return err |
| } |
| log.Infof(l, "Pushing %s to %s", gapiiPath, preloadPath) |
| err = d.Push(gapiiPath, preloadPath) |
| if err != nil { |
| log.Errorf(l, "Failed pushing %s to %s: %s", gapiiPath, preloadPath, err) |
| return err |
| } |
| |
| log.Infof(l, "Setting LD_PRELOAD on %s", p.Name) |
| err = p.SetWrapProperties("LD_PRELOAD=" + preloadPath) |
| if err != nil { |
| log.Errorf(l, "Failed setting LD_PRELOAD: %s", err) |
| return err |
| } |
| defer func() { |
| log.Infof(l, "Clearing LD_PRELOAD on %s", p.Name) |
| err := p.SetWrapProperties("") |
| if err != nil { |
| log.Errorf(l, "Failed clearing LD_PRELOAD: %s", err) |
| return |
| } |
| }() |
| |
| log.Infof(l, "Forwarding port %v", spyport) |
| err = d.Forward(spyport, adb.NamedAbstractSocket("gfxspy")) |
| if err != nil { |
| log.Errorf(l, "Failed setting up port forwarding: %s", err) |
| return err |
| } |
| |
| log.Infof(l, "Starting activity %s/%s", p.Name, a.Activity) |
| d.StartActivity(*a) |
| if err != nil { |
| log.Errorf(l, "Failed starting %s/%s: %s", p.Name, a.Activity, err) |
| return err |
| } |
| return nil |
| } |